Different renderers for datagrid in flex 4.0 - apache-flex

I'm working in flex 4.0 and I have a data grid with three columns. The second column should display the selection(s) the user has made according to the these rules: if they selected only one name display a label with the name in that grid cell, if they chose more than one name then a drop down list should be displayed with a title "Multiple Selected" and the drop down when clicked will show all the names associated for that entry. Therefore the second column can have a mixture of labels and drop down lists. As an example the first entry they chose only one person, so for the first row the second column it shows a label with the person's name. Then in the second entry say they chose 2 names, the second row second column shows a drop down list with the two names in the drop down list. As you can see the second column has a label and a drop down list mixture. Note the selection process is not taking place in the datagrid, the information is simply being supplied by means of setting the dataprovider for the datagrid.

I figure it out you make a itemrenderer with both the label and the dropdown list but you disable one while enabling the other when the conditions are met. The only problem with this approach is I modify the width as well because the label comes first and pushes the drop down list to the right (even when it isn't visible and sometimes beyond the width of the column). So I adjust the widths of each component (setting one to 100% while the other is 0% depending on which is to be visible) but for some reason when I update the data it does not immediately change the cell, only if I click on the header does it change the width and the visibility. I think this is because the UI does not commit the width adjusts immediately? I know it's the width because if I comment out the width adjustments once my data gets updated you see the change right away in the datagrid. For instance if I have not chosen yet the names of my selection, the cell is blank. Then I make a selection of just one person then it shows right away the name in the cell using the label component. Then if I select another name the data gets updated again and you see in the data cell some space (this is the label thats invisible but has some text which causes some empty space) and the drop down list with the names of the ones selected and again it's an immediately effect I don't have to click on the grid to update it. Here's the code with the width adjustments uncommented:
protected function mxdatagriditemrenderer1_dataChangeHandler(event:FlexEvent):void
{
if(data.judgmentpart.JudgmentDebtors.length ==1)
{//display label and disable the dropdown list
lblData.visible = true;
lblData.enabled = true;
lblData.percentWidth = 100;
DDLdatagrid.visible = false;
DDLdatagrid.enabled = false;
DDLdatagrid.percentWidth = 0;
}
else if (data.judgmentpart.JudgmentDebtors.length >1)
{
lblData.visible = false;
lblData.enabled = false;
lblData.percentWidth = 0;
DDLdatagrid.visible = true;
DDLdatagrid.enabled = true;
DDLdatagrid.percentWidth = 100;
}
else
{
lblData.visible = false;
lblData.enabled = false;
lblData.percentWidth = 0;
DDLdatagrid.visible = false;
DDLdatagrid.enabled = false;
DDLdatagrid.percentWidth = 0;
}
}
protected function mxdatagriditemrenderer1_creationCompleteHandler(event:FlexEvent):void
{
lblData.visible = false;
lblData.enabled = false;
lblData.percentWidth = 0;
DDLdatagrid.visible = false;
DDLdatagrid.enabled = false;
DDLdatagrid.percentWidth = 0;
}
]]>
</fx:Script>
<s:HGroup width="100%" verticalAlign="middle">
<s:Label id="lblData" text="{data.judgmentpart.JudgmentDebtors}"
/>
<s:DropDownList id="DDLdatagrid" dataProvider="{data.judgmentpart.JudgmentDebtors}"/>
</s:HGroup>
</s:MXDataGridItemRenderer>

Related

How to enable DevExpress Grid Conditional Formatting?

I have a .net, C# Windows Form project. I'm using DevExpress 19.1. On my GridControl, I have conditional formatting for when a column is less than 0. I want the cell to be highlighted red when the value is less than 0, but it's not working. I've tried using an expression, a condition and value, applying to just a column, applying to the whole role, but I never get the highlighting to work. Can someone tell me what I'm doing wrong?
Here is how the rule looks liked in code:
gridFormatRule3.ApplyToRow = true;
gridFormatRule3.Column = this.colQuantityLeft;
gridFormatRule3.ColumnApplyTo = this.colQuantityLeft;
gridFormatRule3.Name = "Format0";
formatConditionRuleValue3.Appearance.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(128)))));
formatConditionRuleValue3.Appearance.Options.UseBackColor = true;
formatConditionRuleValue3.Condition = DevExpress.XtraEditors.FormatCondition.Less;
formatConditionRuleValue3.Expression = "[QuantityLeft] < 0";
formatConditionRuleValue3.Value1 = 0;
gridFormatRule3.Rule = formatConditionRuleValue3;
this.gvProducts.FormatRules.Add(gridFormatRule3);
Here's how I set the rules in the Designer:
Here's the output where you can see the value is less than 0 and the background color is not changed:
I see that you have only one row in the grid. The grid always has a focused row. The focused row appearance has a higher priority than conditional appearance. Disable the GridView.OptionsSelection.EnableAppearanceFocusedCell and GridView.OptionsSelection.EnableAppearanceFocusedRow properties to remove the focused row appearance.
this.gvProducts.OptionsSelection.EnableAppearanceFocusedCell = false;
this.gvProducts.OptionsSelection.EnableAppearanceFocusedRow = false;
Alternatively, set the FormatConditionRuleValue.Appearance.Options.HighPriority property to true.
formatConditionRuleValue3.Appearance.Options.HighPriority = true;
Set the AppearanceOptionsEx.HighPriority Property to True.

Is it possible to set column name dynamically on a dojo grid?

Is there any way to set a dynamic name for column header, for example in a formatter function!?
I'll have a popup menu on the grid and depending on the chosen option it should change the name displayed in the column header.
Its quite easy if you use dojo.query
var grid = dijit.byId('myGridId'), NewHeader = "Foo Bar Text Content";
var columnHeaderNodes = dojo.query(
'.dojoxGridHeader table th',
grid.viewsHeaderNode)
var nthColumn = 12;
// if has child and its not a textnode - this may happen
// when there is a listener (dnd, click) attached for sorting etc.
if(columnHeaderNodes[nthColumn].firstChild && columnHeaderNodes[nthColumn].firstChild.nodeType != 3)
tgt = columnHeaderNodes[nthColumn].firstChild;
else tgt = columnHeaderNodes[nthColumn];
tgt.innerHTML = NewHeader;

Flex 4: Dynamically created DataGrid with custom ItemRender, problem detecting right cell

<mx:DataGrid id="calendarGrid"
dataProvider="{rows}"
width="100%"
height="100%">
<mx:columns/>
</mx:DataGrid>
I dynamically add columns and rows to it in this way:
var dgc0:DataGridColumn = new DataGridColumn("timeSlot");
dgc0.headerText="Hours";
hoursColumns=new Array();
hoursColumns.push(dgc0);
for (var i:int=7;i<21;i++)
{
var dgc:DataGridColumn = new DataGridColumn();
dgc.headerText=i+":00-"+(i+1)+":00";
dgc.itemRenderer=new ClassFactory(CustomRenderer);
hoursColumns.push(dgc);
}
calendarGrid.columns=slotsColumns;
for(var i:int =0;i<maxNum+1;i++)
{
rows.addItem({timeSlot:"Day n° "+(i+1)});
}
My CustomRenderer detects user clicks and changes the color of the selected cell.
When I select one cell on, say, the first column, it is colored but if I select another cell on the same column the first one is uncolored and the second isn't colored.
Maybe the same renderer is used for all cell in the column?
There's a way to avoid it?
Thanks a lot.
I've got it!
Sorry my second unnecessary question :( my custom renderer constructor has this code inside:
addEventListener(FlexEvent.DATA_CHANGE, resetCell);
which reset cell color, I've remove it and now seems work...
sorry again.

Flex DataGrid Column Width

In my flex app I store the widths and visiblility of columns in an xml file. When the app loads it reads from the xml file and sets he columns values as applicable:
for(i = 0; i < columnsOrder.length; i++){
newOrder[i] = myDG.columns[Number(columnsOrder[i]) - 1];
newOrder[i].visible = (Number(columnsVisiblity[i]) == 1);
newOrder[i].width = Number(columnsWidth[i]);
}
myDG.columns = newOrder;
myDG.invalidateList();
The problem appears to be setting the visibility (it sets the visible field correctly but messes up the width)... I've tried setting it after setting the width (outside of the loop) and before the loop as well. It resizes the columns properly if I don't do anything with the visibility.
Any ideas?
Add an import statement at the top of your class file:
import mx.core.mx_internal;
Then remove using the mx_internal namespace, remove the owner of the column, change the width and then reasign the parent:
public static function resizeColumn(col:DataGridColumn, size:int):void
{
var owner:* = col.mx_internal::owner
col.mx_internal::owner = null;
col.width = size;
col.mx_internal::owner = owner;
}
This ought to do the trick (well, it did for us after a couple of days of swearing)
Is you horizontalScrollPolicy set to false on the datagrid?
"If the DataGrid's horizontalScrollPolicy property is false, all visible columns must fit in the displayable area, and the DataGrid will not always honor the width of the columns if the total width of the columns is too small or too large for the displayable area."
http://livedocs.adobe.com/flex/3/langref/mx/controls/dataGridClasses/DataGridColumn.html#width
I was able to get it to work by calling the above loop in a function twice... the first time it add the visible columns, the second time it sets the correct width. Not the best solution but I cannot spend any more time on it.

Flex: Custom Item Renderer For Combobox controls truncates text

I've implemented a custom item renderer that I'm using with a combobox on a flex project I'm working on. It displays and icon and some text for each item. The only problem is that when the text is long the width of the menu is not being adjusted properly and the text is being truncated when displayed. I've tried tweaking all of the obvious properties to alleviate this problem but have not had any success. Does anyone know how to make the combobox menu width scale appropriately to whatever data it's rendering?
My custom item renderer implementation is:
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
styleName="plain" horizontalScrollPolicy="off">
<mx:Image source="{data.icon}" />
<mx:Label text="{data.label}" fontSize="11" fontWeight="bold" truncateToFit="false"/>
</mx:HBox>
And my combobox uses it like so:
<mx:ComboBox id="quicklinksMenu" change="quicklinkHandler(quicklinksMenu.selectedItem.data);" click="event.stopImmediatePropagation();" itemRenderer="renderers.QuickLinkItemRenderer" width="100%"/>
EDIT:
I should clarify on thing: I can set the dropdownWidth property on the combobox to some arbitrarily large value - this will make everything fit, but it will be too wide. Since the data being displayed in this combobox is generic, I want it to automatically size itself to the largest element in the dataprovider (the flex documentation says it will do this, but I have the feeling my custom item renderer is somehow breaking that behavior)
Just a random thought (no clue if this will help):
Try setting the parent HBox and the Label's widths to 100%. That's generally fixed any problems I've run into that were similar.
Have you tried using the calculatePreferredSizeFromData() method?
protected override function calculatePreferredSizeFromData(count:int):Object
This answer is probably too late, but I had a very similar problem with the DataGrid's column widths.
After much noodling, I decided to pre-render my text in a private TextField, get the width of the rendered text from that, and explicitly set the width of the column on all of the appropriate resize type events. A little hack-y but works well enough if you haven't got a lot of changing data.
You would need to do two things:
for the text, use mx.controls.Text (that supports text wrapping) instead of mx.controls.Label
set comboBox's dropdownFactory.variableRowHeight=true -- this dropdownFactory is normally a subclass of List, and the itemRenderer you are setting on ComboBox is what will be used to render each item in the list
And, do not explicitly set comboBox.dropdownWidth -- let the default value of comboBox.width be used as dropdown width.
If you look at the measure method of mx.controls.ComboBase, you'll see that the the comboBox calculates it's measuredMinWidth as a sum of the width of the text and the width of the comboBox button.
// Text fields have 4 pixels of white space added to each side
// by the player, so fudge this amount.
// If we don't have any data, measure a single space char for defaults
if (collection && collection.length > 0)
{
var prefSize:Object = calculatePreferredSizeFromData(collection.length);
var bm:EdgeMetrics = borderMetrics;
var textWidth:Number = prefSize.width + bm.left + bm.right + 8;
var textHeight:Number = prefSize.height + bm.top + bm.bottom
+ UITextField.TEXT_HEIGHT_PADDING;
measuredMinWidth = measuredWidth = textWidth + buttonWidth;
measuredMinHeight = measuredHeight = Math.max(textHeight, buttonHeight);
}
The calculatePreferredSizeFromData method mentioned by #defmeta (implemented in mx.controls.ComboBox) assumes that the data renderer is just a text field, and uses flash.text.lineMetrics to calculate the text width from label field in the data object. If you want to add an additional visual element to the item renderer and have the ComboBox take it's size into account when calculating it's own size, you will have to extend the mx.controls.ComboBox class and override the calculatePreferredSizeFromData method like so:
override protected function calculatePreferredSizeFromData(count:int):Object
{
var prefSize:Object = super.calculatePrefferedSizeFromData(count);
var maxW:Number = 0;
var maxH:Number = 0;
var bookmark:CursorBookmark = iterator ? iterator.bookmark : null;
var more:Boolean = iterator != null;
for ( var i:int = 0 ; i < count ; i++)
{
var data:Object;
if (more) data = iterator ? iterator.current : null;
else data = null;
if(data)
{
var imgH:Number;
var imgW:Number;
//calculate the image height and width using the data object here
maxH = Math.max(maxH, prefSize.height + imgH);
maxW = Math.max(maxW, prefSize.width + imgW);
}
if(iterator) iterator.moveNext();
}
if(iterator) iterator.seek(bookmark, 0);
return {width: maxW, height: maxH};
}
If possible store the image dimensions in the data object and use those values as imgH and imgW, that will make sizing much easier.
EDIT:
If you are adding elements to the render besides an image, like a label, you will also have to calculate their size as well when you iterate through the data elements and take those dimensions into account when calculating maxH and maxW.

Resources