I have created an item-renderer (IListItemRenderer) to customize the display of a datagrid, and I override the data getter/setter to pass in the relevant variable. So far, so good.
In the item-renderer I have a button, which, when clicked, should display a form populated with various fields of the aforementioned variable. To do this, Button is overridden so that it displays whatever IFactory implementation it is passed.
private function instantiateDropdown():void
{
_dropdownFactory = new ClassFactory(MyPanel);
_dropdownFactory.properties = {boundData: _myVariable};
}
<buttons:PopUpButton id="editButton" dropdownFactory="{_dropdownFactory}" toolTip="Edit" source="{skins.ButtonImages.Edit}" click="edit_clickHandler(event)" />
My IFactory implementation is a panel containing my form, and it is displayed when the button is clicked, as desired. However, the variable is not set. It seems that in order to instantiate my IFactory before the overridden button needs to access it, my new ClassFactory() statement needs to be in the preinitialize event handler, but the variable has not been set at that time. Setting the properties of my IFactory instance after it has been created (e.g. in the click event) does not appear to work.
How should I pass my variable to my ClassFactory-generated instance so that it populates the form correctly?
Using lazy instantiation for the creation of the dropdownFactory (MyPanel in the question) in the class overriding Button (PopUpButton in the question), I was able to call instantiateDropdown in the creationComplete event instead of preinitialize, which allowed the PopUpButton to initialize with the correct properties (_myVariable in the question).
Related
I have a custom MXML component which has a change event declared as:
<mx:Metadata>
[Event(name="change", type="flash.events.Event")]
</mx:Metadata>
The problem is that this event is dispatched whenever I change ANYTHING inside the component including a simple var. There are times when I want to be able to change the value of a var in the component without dispatching a change event. Is there a simple way of disabling the change event and then re-enabling it once I have made the change I want?
I tried to use removeEventListener("change") but it appears I can only do that for a function that has an event listener added. Same for removeEventListener(Event.CHANGE).
Surely there must be a simple way of disabling events declared in
mx:Metadata
yes there are methods on event you can use. So although the event is still dispatched, this gives you complete control of what happens with it.
// first set the useCapture flag to true
// this tell flex that onChange gets the event before it starts bubbling
myCustomComponentThatDispatchesALotOfChangeEvents.addEventListener(Event.CHANGE, onChange, true);
private function onChange(event:Event):void{
// here is the method you want
// this stops the event from bubbling and lets you handle
// all functionality in this listener only
event.stopImmediatePropogation();
// now look at what happened and see if you want to
// do anything else based on what actually changed
}
as a side note, you can also look at Event.preventDefault() which cancel's the events default behavior
"change" is also a flex thing. It you want to only dispatch the event in one particular scenario, make a new event class that SubClasses Event like MyChangeEvent. The when you make your change...
dispatchEvent(new MyChangeEvent(MyChangeEvent.STUFF_CHANGED))
then
myCustomComponentThatDispatchesALotOfChangeEvents.addEventListener(MyChangeEvent.STUFF_CHANGED, onChange);
I always have a question about override custom event. I am not sure why or what do to inside override function. I searched google but didn't get too many feedbacks. I appreciate if someone can light me up. Thanks.
EDIT:
My projects seem work fine even though I use my custom event without override. Anyone could explain it? Thanks.
In general, you need to override a function when its use needs to be modified. So for instance, say I have a class called Car. In this class I have a function called go() which starts the car.
Now if i extend this class into another class called PickupTruck, I need to override the Car class' go function so it not only starts the car, but also attaches the Trucks trailer.
So in your case you have to override the clone method of your CustomEvent class because it should return a new CustomEvent instead of a new Event.
From the docs:
When creating your own custom Event
class, you must override the inherited
Event.clone() method in order for it
to duplicate the properties of your
custom class. If you do not set all
the properties that you add in your
event subclass, those properties will
not have the correct values when
listeners handle the redispatched
event.
So, you can have a problem if you don't override clone and redispatch an Event. Also, the problem is not only that the custom properties will not be copied. The clone method will be called on the base class, Event. This will return an Event object, not a CustomEvent. If you have a handler that expects a CustomEvent and receives an Event, an error will be thrown and the code in your handler will not run.
I have a two way binding between a loaded flash file and the main application in flex.
BindingUtils.bindProperty(this, "micGainValue", audioPublisherApp, "micVolume");
BindingUtils.bindProperty(audioPublisherApp, "micVolume", this, "micGainValue");
micGainValue=75;
However, the setting of micGainValue does not set micVolume in the flash file. I instead tried setting micGainValue after 200 frames, and it now does set micVolume. Is there a way to test that these properties are bound and so set the value after?
EDIT:
The flash file was actually changing the value. Now the question is, why does setting micVolume not change micGainValue.
This the code from my loaded flash file:
[Bindable]
public function get micVolume():Number{
if(microphone!=null)
return microphone.gain;
return 0;
}
public function set micVolume(val:Number):void{
if(microphone!=null)
microphone.gain=val;
}
Flex databinding is implemented using events. When you use BindingUtils.bindProperty, what is happening behind the scenes is that an event listener is being added to the target object to listen for an event of type PropertyChangeEvent
If the target object does not dispatch the PropertyChangeEvent when it is changed, then binding will never be triggered.
When you add the [Bindable] attribute to properties in Flex, what you are doing is telling the framework to dispatch the PropertyChangeEvent when that property is changed. If you don't include the attribute (or put it on the class) then the event is not dispatched and binding doesn't happen.
That's why your binding is working from Flex to Flash but not the other way around- The Flex object is dispatching the required event when it is changed but the flash object is not.
Here is the info on PropertyChangeEvent
Personally, for Flash -> Flex I would dispatch my own event when the flash part changes its values and use a handler on that to update a bindable object within the Flex part. You can then bind other Flex stuff to that.
Flex 3 question:
I trying here to avoid having to bind resources to all my components labels ( ie a button) and find a way to have this automated.
Problem:
It corrupts the layout in design mode to bind directly in the mxml label="{resourceManager.getString('myResources', 'submit')}" and makes the design view useless. but when declaring bindings elsewhere, in actionScript or via a bind tag, it is counter productive and prone to many errors and miss.
Proposition:
I would like to create my own button that automatically invoke resources to localize a button label. So the author puts "Submit" in the mxml description of my button, and when running it would take the value of the label ie "submit" and use resourceManager.getString('myResources', 'submit').
but I can't find the way to override the set label function, Is it possible if yes how? else how can I go about it?
Maybe I am missing an essential process here that would make the use of resources more elegant, as well as how to override such thing as a button's label.
Thanks for your advices.
Create a component called MyButton, extending Button. Then use this:
override public function set label(value:String):void {
super.label = resourceManager.getString('myResources', value) || value;
}
Assuming the resource manager returns "null" or "undefined" this will work, and will only replace the value if it exists in "myResources".
If you don't want to override every component you need to do this with, then you can add a FlexEvent.CREATION_COMPLETE event on every component. Then use a single generic function to do your label localization.
Ok, please understand the architecture here first.
OurMasterPage.aspx has user control Header.ascx
Header.ascx has a user control in it called LandingPageTopNav
LandingPageTopNav.ascx has a public property named "LandingPage" that is there to be able to set by the user using this control.
And I have a Third.aspx page in which I need to set the LandingPageTopNav property to a LandingPage object
The problem is that I can't get this to work in my ThirdPage.aspx.cs:
Master.LandingPageTopNav.LandingPage = this.landingPage;
Master.LandingPageTopNav.Visible = true;
And that is, I can't get the first line to work where I'm trying to reference the LandingPage property. The second line is fine. My Third.aspx definitely can reference my master page objects otherwise from code-behind.
I'd venture to guess that the LandingPageTopNav property of OurMasterPage doesn't return a value typed as LandingPageTopNav. It probably returns the correct control typed as something more generic (e.g. Control); which is why setting the Visible property works but not the LandingPage property.