By default, whenever you rollOver/mouseOver (not sure of the difference) an item in a Datagrid or a List, that item is highlighted with the component's rollOverColor. I'm just wondering if there's any way to do that programmatically. I haven't been able to find much help on the issue. For example, suppose I have two DataGrids. When I rollOver an item in the first DataGrid, I want to highlight the corresponding index in the second one as well. Basically, as if two separate cursors were rollOver'ing two separate DataGrids. How can I do this?
Ian
You can listen for the datagrid's itemRollOver event and then select a row in the other datagrid by using it's selectedIndex or selectedItem properties.
1) Create a custom DataGrid with this function :
public function indicesToItemRenderer(rowIndex:int, colIndex:int):IListItemRenderer
{
var firstItemIndex:int = verticalScrollPosition - offscreenExtraRowsTop;
if (rowIndex < firstItemIndex ||
rowIndex >= firstItemIndex + listItems.length
)
{
return null;
}
return listItems[rowIndex - firstItemIndex][colIndex];
}
2) When you want to hightlight an item, call this code :
youCustomADG.indicesToItemRenderer(idxRow, idxCol).dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OVER);
Related
I have a generic Grid List Control. Which let me Bind the Item Source and ItemTemplate and it will generates the Column and Rows based on Number of Items or Based on how Users set the Rows and Columns. Its perfect until here. It supports all the generics I needed.
Now the Problem part:
I have a ContentView which will be used as Item Template for the Grid. This Template will be used for Multiple Data Types. I'm able to do it properly. Now I have one Data Type Where the First Cell should have RowSpan if it meets certain condition: The code below works perfect. It creates the RowSpan perfectly.
bool isYearBuilt = false;
bool isAny = false;
public FilterItemView()
{
InitializeComponent();
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
var context = BindingContext as PropertyFilterItem;
if (context == null)
return;
if(context.FilterType==PropertyFilterTypes.YearBuilt)
{
if(context.IsAny)
{
isYearBuilt = true; isAny = true;
}
}
}
protected override void OnParentSet()
{
base.OnParentSet();
GridList grid = this.Parent as GridList;
if (grid == null)
return;
if(isYearBuilt && isAny)
{
Grid.SetRowSpan(this, 2);
}
}
These are the Images; which will describe it more perfectly:
This is how it looks based on above code. We can see that it is creating RowSpan.
This is what I'm expecting to do.
The only problem is - While Setting RowSpan it is not refreshing the subsequent cells. Because, I'm applying the RowSpan in Runtime after the Grid and all the Cells are created. How can I refresh the Grid and other remaining cells to moved to their own cells?
Thank you for helping me.
Set the grid list's ItemsSource = null and set it back again to the item source you want.
Cause of the problem:
As you have said, While Setting RowSpan it is not refreshing the subsequent cells.
Solution:
After you have set rowspan using Grid.SetRowSpan(this, 2); you have to bind the datasource again.
Since I had my own Custom Grid List control. I implemented more Properties which let me know When I have to RowSpan for Child View in Grid and Adjust subsequent Child items. That was the only best way to deal with this problem rather than re-assigning the ItemSource property. Because, If we assign item source it will redraw all the items (including the rows and columns - not row/colspans). So we would still end up with same issue.
Solution: Added RowSpan logic in my Grid Control.
I have a grid I created in Gridx which lists a bunch of users. Upon clicking a ROW in the grid (any part of that row), a dialog pops up and shows additional information about that user and actions that can be done for that user (disable user, ignore user, etc.) - when one of these options is selected from the pop up, I want to DISABLE that row. The logic for getting the row, etc. I can take care of, but I can't figure out how to make a grid row actually "appear" disabled and how to make that row no longer clickable.
Is there a simple way to do this? If you aren't familiar with gridx, solutions that apply to EnhancedGrids or other Dojo grids are also appreciated.
Alright now that I have a little more information here is a solution:
Keep a list of all the rows you have disabled so far either inside the Grid widget or in its parent code. Then on the onRowClick listener I would write code like this:
on(grid, "onRowClick", function(e) {
if(disabledRows[rowIndex]) {
return;
}
// Do whatever pop up stuff you want and after
// a user selects the value, you can "disable"
// your row afterwards by adding it to the disabled
// list so that it can no longer be clicked on.
var rowIndex = e.rowIndex;
disabledRows[rowIndex] = true;
// This is just some random class I made up but
// you can use css to stylize the row however you want
var rowNode = e.rowNode;
domClass.add(rowNode, "disabled");
});
Note that domClass is what I named "dojo/dom-class". Hope this helps!
This is perhaps not exactly what you are seaching for:
If you want to hide one or more rows by your own filterfunction you could just add to these rows in the DOM your own class for nodisplay. Here I show you a function for display only those rows which have in a choiceable field/column a value inside your filterlist.
function hideRowFilter(gridId, fieldName, filterList)
{
var store = gridId.store;
var rowId;
store.query(function(object){
rowId = gridId.row(object.id,true).node();
if (filterList.indexOf(object[fieldName]) == -1)
domClass.add(rowId, "noDisplay"); // anzeigen
else
domClass.remove(rowId, "noDisplay"); // verstecken
});
}
CSS:
.noDisplay { display: none; }
So I can for example display only the entries with a myState of 3 or 4 with this call:
hideRowFilter(gridId, 'myState', [3, 4]);
Note that domClass is what I named "dojo/dom-class"
How we can hide a row at specific index of DataGrid in AS3 ?
If dataProvider of your DataGrid is ArrayCollection you can specify filterFunction property for it, something like that
dataProvider.filterFunction =
function (item:Object):Boolean{
if (dataProvider.getItemIndex(item)==indexOfRowYouWantToHide){
return false;
}
return true;
};
The item will still be in ArrayCollection but will be made invisible by the filter. Not the most efficient solution but it works. You need to call
dataProvider.refresh();
to apply the filter.
UPDATE: To access raw, unfiltered data of ArrayCollection you should use list property, so if you hid item at index 0 and still want to be able to access it you do that like this:
dataProvider.list.getItemAt(0);
No (easy) way. You can try to subclass DataGrid to add this functionality, but this will be really heavy task.
I have an item renderer that checks an external source for display information. If that information changes, I want to force all item renderer instances to check it.
What's the best way for force all the item renderers in a list or grid to either commitProperties or execute some other method?
I've read that resetting the
grid.itemRenderer property will make
them all initialize.
I've also received the suggestion to
iterate recursively through all the
grid's children and call invalidateProperties
on all the UIComponents I find.
Any thoughts? Alternatives?
Remember that in Flex Lists you're dealing with virtualization and itemRenderer recycling, so generally only the currently visible itemRenderers actually exist, and are therefore the ones that actually need updating.
The following works for Spark list-based controls:
for ( var i:int=0; i< sparkList.dataGroup.numElements; i++ )
{
var element:UIComponent = sparkList.dataGroup.getElementAt( i ) as UIComponent;
if ( element )
element.invalidateProperties();
else
trace("element " + i.toString() + " wasn't there");
}
If you've got 100 items, this will update the 10 visible ones and ignore the virtual rest.
If you're working with mx DataGrid, you might want to try a variant of this- but it doesn't use DataGroup / Spark virtualization so I don't have an answer for you off the top of my head.
P.S. I'm putting the finishing touches on a completely Spark-based DataGrid, I'll post the link when I'm done.
Datagroup has getItemIndicesInView() which will give you the indicies of all item renderers that are in view. Call getElementAt with those indicies.
I also usually extend ItemRenderer and add the following which will cause the item renderer's state to refresh.
public function invalidateSkinState():void
{
super.invalidateRendererState();
}
public function updateAllRenderer():void
{
if (!list.dataGroup)
return;
if (!list.dataGroup.dataProvider)
return;
for ( var index:int=0; index< list.dataGroup.numElements; index++ )
{
var item:Object = list.dataGroup.dataProvider.getItemAt(index);
var renderer:IVisualElement = list.dataGroup.getElementAt( index ) as IVisualElement;
if ( renderer )
list.updateRenderer( renderer, index, item );
}
}
works fine for me
I have a Flex ComboBox that gets populated by a dataprovider all is well...
I would now like to add a default " -- select a item --" option at the 0 index, how can I do this and still use a dataprovider? I have not seen any examples of such, but I can't imagine this being hard...
If you don't need the default item to be selectable you can use the prompt property of ComboBox and set the selectedIndex to -1. That will show the string you set propmt to as the selected value until the user chooses another. It will not appear in the list of options, however.
I came across this problem today and wanted to share my solution.
I have a ComboBox that has an ArrayCollection containing Objects as it's dataprovider. When the application runs, it uses a RemoteObject to go out and get the ArrayCollection/Objects. In my event handler for that call I just have it append another object to the beginning of the ArrayCollection and select it:
var defaultOption:Object = {MyLabelField: "Select One"};
myDataProvider.addItemAt(defaultOption, 0);
myComboBox.selectedIndex = 0;
This is what my ComboBox looks like for reference:
<mx:ComboBox id="myComboBox" dataProvider="{myDataProvider}" labelField="MyLabelField" />
The way I've dealt with this in the past is to create a new collection to serve as the data provider for the combobox, and then I listen for changes to the original source (using an mx.BindingUtils.ChangeWatcher). When I get such a notification, I recreate my custom data provider.
I wish I knew a better way to approach this; I'll monitor this question just in case.
This can be used following code for selected default value of combobox
var index:String = "foo";
for(var objIndex:int = 0; objIndex < comboBox.dataProvider.length; objIndex++) {
if(comboBox.dataProvider[objIndex].label == index)
{
comboBox.selectedIndex = objIndex;
break;
}
}
<mx:ComboBox id="comboBox" dataProvider="{_pageIndexArray}" />