Flex: DataGrid and the Command Pattern - apache-flex

I am using a command pattern, so any changes to object state need to happen within a command execution. A normal itemeditor in a DataGrid would just make its changes on the underlying bound object, but I need to intercept that change and make it use a command.
I'm pretty new to flex, so I'm looking for ideas of how to implement this. A basic example is that I have an object with a "date" field. In the datagrid I am using a flex "DateField" component as the itemeditor. When I select a new date, I don't want it to update the datasource, I want it to call a different method where I can access the newly selected value and pass it to a command to execute. Any tips would be greatly appreciated. Thanks in advance.

Use the itemEditBegin and/or itemEditEnd events on the DataGrid and build your command in the handler. This page has a few examples of capturing the edit operation with those events.

In my opinion, you're over-engineering this to hell, to the point that it becomes unusable. Why would you need a command to just change data on the fly? I've been doing Flex for 3 years and I yet to see it done this way. The only time commands are used is for receiving information from the server.
Either way, if you really want to implement it (against my recommendation), you would probably want to do event bubbling with a controller listening higher up the display list for the event, then from there trigger a command. From within the item renderer:
this.dispatchEvent(new Event('someEvent', true));
And then higher up the display list:
dataGrid.addEventListener('someEvent', someEventHandler);
And within the handler you can run the command.

Related

JavaFX binding in initialize method

I am trying to create a binding to provide a button a way to disable/enable itself whenever a listview contains items or not. However, I don't get it to work.
This is my initialize method
private void initialize(){
runButton.disableProperty().bind(Bindings.isEmpty(listView.getItems());
}
Adding items to the listView has no effects whatsoever on the disabled/enabled state of the button.
If I put the above line of code in another random function that is called later on in the program, it works.
I've read that the bindings might be garbage collected so I've also tried to create a field of the binding to then apply to the disabledProperty. This does not work either.
Any ideas?
EDIT:
listView.setItems(observableFiles)
is used to populate the list
Do you call listView.setItems() anywhere in the code? If so that will explain why it doesn't work when you put it in initialize because you're binding to the old list object whereas the ListView is using the new list object.
Edit: Just seen your edit, it seems you really did this. Try calling the bindings after you call setItems.
As another alternative you could add listener to ListView itemsProperty and if the changed list is empty trigger disable on your runButton.

Populate comboboxes INSIDE a datagrid with UNIQUE data IN actionscript (flex)

i've searched for several hours, and didn't find an answer for my problem.
i'm trying to place comboboxes in a datagrid filled with DYNAMIC data. (the number and the content of these comboboxes always change. i don't know in advance how many columns there are, where i need to use comboboxes. so every single combobox gets a unique dataprovider, which comes from an external source, WHEN the program runs.)
-i found MANY threads discussing this problem, but solving via crappy mxml files, filling the comboboxes inside the sourcecode by hand. i want to point out, that isn't good for me.
-i found a better solution, in which they used some sort of custom itemrenderer to get the data from the internet. (kind of a country chooser thing) but sadly that wasn't good enough, because the number and name of the countries in the world are static more or less, they don't change. so their renderer class didn't depend on any parameters from the main algorithm.
but in my program i calculate the data in my own actionscript objects, then fill an arraylist with that. so at the beginning i load the desired data from the net, and when i get the response of the urlrequest, AFTER that i start to populate the datagrid/combobox.
i can fill any datagrid or combobox without trouble, but to put that combobox inside a datagrid cell seems to be impossible.
could anyone please help? it drives me crazy. i managed to do this in several languages before, c#, java, even php+html, but in flex it looks way too complicated then it should be.
EDIT:
i'm aware, that this amount of network activity could mean some load on the server. i didn't design the philosophy behind it, i just need to wrote a client which meets the expectations. my program looks something like this:
(i'm willing to rewrite any part of it, just to make those nasty comboboxes work)
=========
main.mxml file
this is the main program, i handle some login related stuff here, and set basic design properties for the datagrids. (for example: maxwidth, maxheight, layout constraints etc.)
nothing interesting, except the command when i instantiate the actionscript class, which i wrote to fill the datagrid.
"..<fx:Script>
<![CDATA[
private var myGrid1:MyGridType;
..
somefunction {
myGrid1 = new MyGridType(theDatagridDefinedBefore, "argumentNeededToFillDataGridsWithUniqueData");
}
]]>
</fx:Script>.."
=========
MyGridType.as file
in the constructor i call a urlrequest with the help of the second argument, then add an eventlistener to it. when the data arrives, the eventlistener fires the filler function: i read the results into an arraycollection, then make it the dataprovider for the the datagrid in the first argument.
so far so good.
here comes the trouble with the comboboxes. for a specific number columns, i instantiate my combobox class. let's call that class "MyComboBoxType".
"..
blablabla = new MyComboBoxType(theDatagridDefinedBefore, param1, param2, param3);"
=========
MyComboBoxType.as file
i do nearly exactly the same, what i did in the MyGridType class. call for help from the net with param1-2-3. when i receive the data, fill an arraycollection. maybe set that arraycollection to be the dataprovider for a combobox. AAAAAAAND now i want that arraycollection or combobox to be on the datagrid "theDatagridDefinedBefore".
I know it's not exactly what you're trying to accomplish, but I had a somewhat similar issue in the past. Take a look at How to get the value of a ComboBox within a DataGrid to see if it helps.
If it were me, I would populate the entire ArrayCollection set before binding them to the datagrid if at all possible.
You should build up your custom [Bindable] data structure - say MyGridData class - for the rows in the grid (if you haven't done it yet);
the dataProvider of your grid should
be an Array / ArrayCollection /..
of MyGridData objects.
this step clearly works already, but
for the integrity: override the
getItemEditor function, or specify
it explicitly using mxml, to return
the combobox when needed.
as for the dataProvider of the
combobox, you should specify the
data.comboArray from inside the
renderer class, where data is the
MyGridData instance used by the row
you are processing. (overriding the
set data(value: Object):void
function, you can pre-process it.)
this way, you are working with the
reference of your original instances,
and by the binding you can detect /
show any changes to them directly.

Flex, filter tree using ITreeDataDescriptor without reload and close all nodes

working with flex 4 and implementing filtering using ITreeDataDescriptor.
Filtering worked as expected like the following code snippet
however, i am trying to create a on-demand type of filter where user would type in the search clause in a TextInput, and as the user types, the tree nodes would be filtered on the fly.
my implementation now is have user click on the search button and then reapply the dataDescriptor then reload the data. A big problem is that the whole tree collapses after setting the dataProvider again.
any suggestion on how the on-demand filter can be achieved?
var dataFilter:ServicePricingFilter = new MyFilter();
dataFilter.searchString = this.txtSearchKeyword.text;
this.treeService.dataDescriptor = new MyDataDescriptor(dataFilter);
this.treeService.dataProvider = getTreeData();
I think you shouldn't set the dataprovider every time but use insted the filterFunction property available for ListCollectionView classes (ArrayCollection, XMLListCollection,...)
looked at the post Florian mentioned.
on-demand filtering is done by using ITreeDataDescriptor and a filterFunction.
on keyup event of the search TextInput, call invalidateList() function on the tree.
see the source code provided for the following post
http://www.davidarno.org/2009/04/01/how-to-filter-all-nodes-of-a-flex-tree-component/

How Do I See All Events Fired by an Object?

I am having trouble wiring up an event listener to a fl.transitions.Transition.
Is it possible to somehow view all the events an object fires? That way I could check I am using the correct event (and possible view better ones to use).
The easiest is to override the dispatchEvent method in classes where you want to intercept events.
You can find the classes in %CS_ROOT%\Common\First Run\Classes\mx\transitions\easing\.
You can also create a subclass of EventDispatcher with a custom dispatchEvent-implementation and use that as a subclass for all classes where you'll be wanting to intercept events.
greetz
back2dos
The problem is, you have to have an event type to listen for. The only way to do this is to add listeners for all the possible events.
Now, you can add a handler with an indeterminate event type, such as:
private function myUniversalHandler(event:*) : void {
trace(event.type);
trace(event.constructor.toString());
}
And this will report any event passed to it. Nevertheless, it simply won't be called unless it is listening for an event of a particular type. And adding all those listeners is a lot of work to go through. Better to study the events available to you from whatever class you are dispatching the vent from.
I would look at TransitionManager, and the events allTransitionsOutDone and allTransitionsInDone which it dispatches. I haven't used these, but my understanding of their function matches what you seem to be looking for.
checkout the online reference, you should see there all events (and inherited events) of a Class.
On a side note if you are using flex you might be using mx.states.Transition
There is no way, at runtime, to find out all the events that fire from a component. You'll have to explore the component source code to get a complete list.
Reviewing the ASDocs, as others have suggested, is a good way to get a handle on the documented events of a component; and in most cases you'll be able to find one to suit your needs.
You cannot programmatically get a list of all events fired by any given object. You can however get a list of all events fired by a standard library object (that are part of it's public interface) from its documentation (cilck on the show inherited events link) and decide whether you're using the appropriate one.
I have scratched my head quite a bit on this issue as well.
The answer is this
you can get a list of all event listeners that an object is listening to only if attached though MXML
if not attached through MXML you cannot see the events an object is listening to (attached by AS)
if you want to see all the events an object is listening to you can check for hasEventListener although this is a long coding way
another efficient way (if you can use it, I couldn't) is to monkey patch the framework and create a dictionary of listeners for every object.
you can accomplish that by patching FlexSprite and overriding the addEventListener function.
you should keep in mind, this will not work when you are loading the framework through RSL.

ASP.Net: Is it possible to skip databinding of an element if an error occurs?

I use a lot of repeaters for different elements of our sites, and I've always wondered if there was a way to have the repeater skip an element if an exception occurs instead of having the whole page crash?
In particular, I've inherited a system from another developer that using a similar design, however he didn't include any kind of validation for his business objects, and it a single property is missing, the whole thing goes up in smoke.
Any suggestions?
Thanks in advance!
The simplest suggestion I can offer is the check the validity of the data before it's passed to the repeater. I don't believe there's any way to get the stock repeater to skip a data element on error.
The other approach is to build your own repeater, inheriting from the base Repeater, to add that functionality but I've no sample code to offer. Perhaps someone else may be able to help there.
The way I see it, you have at least three options.
You could create a custom repeater control that inherits System.Web.UI.WebControls.Repeater and override the databinding behaviour to be more try-catchy (probably fail silently on databinding errors). You couldd then easily replace all instances of the standard Repeater with this new one.
You could filter your datasources before databinding to remove items you know are going to cause problems beforehand. This option may be quite laborious and something of an iterative process.
You could try adding default values to the business objects, so that the properties you're binding to return a default instance rather than null (not nice either).
That's my thoughts anyway.
One question - you say "when a property is missing". Do you mean he's using a style of databinding syntax that offers no compile-time checking and is referencing properties that don't exist, or is referecing properties that are null?
Edit
OK, so you're referencing properties that are null. If you have access to the code for the business objects you could modify them so they return a new, non-null instance (this is the third option I gave).
You don't say if you're using .net 3.5, but I'll assume you are. You could add a new property "IsValidForDataBinding" on to each of your business objects. In the getter logic you could check each of the necessary properties and sub-objects to check for validity, non-nullness etc and return a bool. When you come to bind your repeater, write a simple linq statement that filters-out the invalid items (i.e. where IsValidForDataBinding = false). Having said that, I still think that writing a derived repeater control could be your easiest option.
Have you tried using string.isnullorempty("the string") to check for a value before referencing the property?
Here's a reference: MSDN

Resources