Actionscript 3 Bind variables - apache-flex

I am trying to set one bindable variable to be bound to another. Essentially I want to create an alias. I would give up, but this seems like something that would be good to know.
essentially, I want changes in model.configView to be reflected in view, so that things bound to view.... behave the same as things bound to model.configView... in this example [Bindable]
var view = model.configView;
...
<mx:Label text="{view.lblThisLabel.name}" />
at the moment it does not, and I am getting errors that say "unable to bind to property 'lblThisLabel' on class 'Object' (class is not an IEventDispatcher)"

Not quite enough code here to really say what's going on, however you have made view bindable and that does not automatically mean that all of view's children are bindable. You'll have to go into view and make lblThisLabel bindable too.
Also it is hard for the rest of us to know how it works in your head. Perhaps you should describe that too.

Moreover, I think that even if, with your actual code, view changes should be detected, view won't be updated if assigned model.configView property is not bindable as well...

Related

How to use databinding with s:GridItemRenderer and anonymous objects?

I have a custom s:GridItemRenderer that contains a single s:CheckBox and is used to display a boolean property of the items in the grid's dataProvider which is dependend on which dataField was set for the column:
<s:GridItemRenderer>
<s:CheckBox selected="{this.data[this.column.dataField]}"/>
</s:GridItemRenderer>
I can't (or rather: I don't want to) hardcode the property since I want to keep the renderer as generic as possible and hardcoding the property name would require me to write at least 2 otherwise identical renderers.
Now the problem is that the dataProvider contains only anonymous objects (e.g. {foo:"blah", bar:"blubb", isBaz:true}) and databinding doesn't work with hash lookups. Since the property name is not fixed but also dynamic, I cannot use the dot syntax to access the property on the objects.
I've already searched the web for a possible solution, but didn't find any that worked. I tried using an mx:ObjectProxy as a wrapper for the data item as suggest here but that didn't work. I tried manually creating the binding with mx:BindingUtils.bindProperty() as suggested here but that didn't work either.
Is there any way to achieve databinding in that situation?
During some refactoring the structure of the dataProvider changed and I was required to write specific itemRenderers for each datagrid, so the generic approach is no longer supported and the issue basically resolved itself. :)

Setting bindable value to label in Actionscript (no curly brackets in mxml)

I've got a model class with custom change events, which is working fine if I make a reference to that class in my mxml using;
[Bindable] private var firstClass:FirstClass;
The objects gets filled by a server side script, so don't worry, firstClass isn't null.
Anyhow, accessing firstClasses properties in mxml works perfectly fine using curly brackets. The binding works just as expected.
However, is there any way to access firstClasses properties and set them to say a label with pure Actionscript.
lblTest.text = firstClass.property;
The code above doesn't work. I suppose because it sets a fixed value to the label.
I'm aware of using BindingUtils.bindProperty to explicitly set the source and destination for the binding. However, this turned out to cause huge performance issues in my (mobile) application.
So is there a simpler, more efficient way to do this?
No. The BindingUtils uses propertyChanged events to detects when an object's property changes. You won't be able to bind something without listening to events, and the most painless way to do it is using BindingUtils.

Is there a reliable way to "refresh" a component?

By "refresh" I am completely disposing it and then introducing it again in the application (without closing the application itself - that is). Other than than I think the question is self-explanatory.
Example:
Say I have a component named myComponent. I add that component to the application using MXMl in the standard way <components:myComponent id="myID" />. Say that when a user clicks a button (the button may be in another state), the component with id myID should be garbage-collected and a new instance of it added to the application.
How do I go about doing that? If there are multiple solutions which one is the optimal performance-wise?
I am new to Flash and Flex so excuse me if any incorrect terminology were used.
Remove all the event listeners from the old component; whatever they are using the removeEventListener method:
myButton.removeEventListener(someEvent, someEventHandlerMethod);
Then all variables that refer to the component should be set to null. If created in an MXML file, like this:
<s:Button id="myButton" />
Then all you have to do is set that value to null:
myButton = null;
Once there are no references to the component, it can safely become eligible for garbage collection.
If you want to re-created, then just re-created it. You'll have to re-create it in ActionScript, but the code isn't hard. Conceptually something like this:
myButton = new myButton();
myButton.properties = propertyValues;
myButton.addEventListener(someEvent, someEventHandlerMethod);
parentContainer.addChildAt(myButton, whateverPositionYouWantToADdTheComponentAt);
I'm not sure I see the benefit of doing this. I suspect it'll be much more efficient to tweak the existing button instance in the way you need to as opposed to destroying it and trying to replace it with the exact same thing.

Accessing properties of AdvancedDataGrid runtime vs. design time

I am new to Flex and trying to modify some existing code. I am trying to It uses and AdvancedDataGrid. In the click event, the ListEvent is passed in, and the code is able to access properties such as event.itemRenderer.data.feature.
I would like to check whether the user has clicked on a parent (group) record or the child record; at runtime, I can see that the property I want to access is event.itemRenderer.listData.hasChildren. However, the listData property of itemRenderer does not show up in intellisense, and when I try to access that at design time, the project will not build because of the error "Access of possibly undefined property listData". But the property .data.feature doesn't show up in intellisense at design time either, and that builds and runs just fine.
What do I need to do to access event.itemRenderer.listData without throwing errors when I build the project? Do I need to capture a different event, or cast the event object or one of its properties into another object that will have the properties I need at runtime (I've investigated these options but cannot find info on how to do that).
Many thanks for any insight.
You probably have to perform a cast using IDropInListItemRenderer and AdvancedDataGridListData. Something like this:
((event.itemRenderer as IDropInListItemRenderer).listData as AdvancedDataGridListData).hasChildren

silverlight - binding to two objects

I want to create a user control, which can be bound to some data given from outside the control (requirement A), and some XAML properties must be bound to properties of the control itself (requirement B).
Let's say that I have a data class named StudentData and a control named StudentControl. I'm using this control inside a DataGrid. I put the StudentControl in the grid with a DataGridTemplateColumn. I somehow bind the StudentData in the current cell to the control. This is requirement A. This StudentControl wants to specify if some of the controls inside it are editable or not. The best way to do this is exposing a property, like StudentControl.AreSomeControlsEditable. Then I can bind the IsEnabled property of those controls to this property. This is requirement B.
Here's my first idea. I bind the current StudentData to a DP of StudentControl, then, inside the StudentControl, I change the data context to the control itself:
<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}">
<TextBox
Content="{Binding Path=ExposedStudentData.Field1}" *reqA*
IsEnabled="{Binding Path=OtherProperty1}" /> *reqB*
</UserControl>
This way, I figured, the StudentControl gets the StudentData from outside, exposes this same StudentData and the other new properties (so the data and other properties are in one place now, not two), and then I can bind to these exposed properties in XAML (reqA+reqB are fulfilled at the same time). Except this doesn't work because of this bug. Basically, if I set the DataContext of the control to itself, then it gets set before the outer binding is applied. So if my binding path inside the cell is X, and then the data context changes, the binding engine will look for X in the new, self data context, and not the outer, grid data context.
Here's my second idea. I bind the current StudentData to the DataContext or a DP of the StudentControl. Then, to access other exposed properties of the StudentControl, I give a name to the UserControl and use ElementName binding:
<UserControl x:Name="self">
<TextBox
Content="{Binding Path=Field1}" *reqA*
IsEnabled="{Binding ElementName=self, Path=OtherProperty1" /> *reqB*
</UserControl>
This way, I figured, the current data context is the StudentData, and it's not changed, and I can bind to that with a simple path (reqA), and I can bind to the other exposed properties with the ElementName stuff (reqB). It works in basic scenarios, but not in a DataGrid, because of this bug. I'm guessing the problem arises when there are multiple controls with the same name in the visual tree.
I'm really starting to hate Silverlight, I started using it a month ago, and I already reported 9 bugs. Whenever I try to achive something other than a simple hello world application or something that Microsoft and everyone else seems to be using Silverlight for, I encounter a new bug. So what now, how would you bind to a data class given from outside the control and some other properties exposed by the control at the same time? Without, of course, setting up the bindings from code (which I'm doing now, but it's a nightmare with ListBoxes and DataTemplates) or not using binding at all.
I think your problem is with the DataContext and how it is inherited, as well as namescopes.
For the first, you should know that if a control doesn't specify its own DataContext, it will inherit that of its parent, and for ItemsControl derived controls, each Item will have its DataContext set to one of the data items in the ItemsSource collection.
For your second problem, if you're inside a DataTemplate, you're in a different namescope than outside of it. You can't access controls "by name" outside of a DataTemplate. What you can do here (for Silverlight 4 and below) is to traverse the Visual Tree yourself and look for the control you want. This, however, is going to become much easier and less painful with some new features in SL5, specifically the "FindAncestor" feature (which already exist in WPF).
Here's an article on MSDN about Namescopes in Silverlight. And here's another one about DataBinding which mentions how DataContext is inherited.
To achieve what you're looking for, I think this blog post should help you. It shows you how to implement "RelativeSource Binding with FindAncestor"-like behavior in Silverlight.
Hope this helps :)
On another forum, they told me to use MVVM. As it turns out, it can make my first idea a little better. Instead of binding my StudentControl to a StudentData, and then exposing this data and other properties, I should create a viewmodel, let's say StudentControlData, which contains a StudentData and additional properties required by the control. If I bind my control to this, then in the inherited data context of the control, I have access to all properties that I need. Now the only problem left is that inside a ListBox in my StudentControl, I lose this data context.

Resources