Flex Datagrid Itemeditor:显示选择标签,但在提交时检索值

时间:2014-03-10 03:27:25

标签: xml flex datagrid itemrenderer itemeditor

(编辑:请参阅下面提供的答案作为可能的解决方案)

我有一个datagrid,其中每个datagridcolumn使用不同的itemrenderer。其中一列中的其中一个渲染器是一个充满值的List组件。列表组件中显示的文本是其数据提供者的标签。

我想要做的是使List组件列itemrenderer成为一个itemeditor。这意味着用户单击列中的单元格并显示值列表(不是下拉列表)。然后,他们可以从列表组件中选择多个值。当他们单击List组件时,该列显示所选的值。

当他们保存他们的选择时(通过相关数据网格外的保存按钮),我想引用这些数据来确定他们做出了什么选择 - 但是 - 而不是标签,我想得到这个数字与该标签相关联。我用XML做到这一点:

<colors>
<color label="Green" value="1"/>
<color label="Yellow" value="2"/>
<color label="Red" value="3"/>
</colors>

现在,itemeditor部分非常棒,因为它可以在单击单元格外部后直观地看到您的选择。但是,我想确定所选颜色的值(“3”),并对此列表中选择的每个值执行此操作。

这应该通过以下datagridcolumn自然识别(CheckList只是一个允许多次选择而不按住CTRL键的List),使用此列的给定数据提供者:

<colorData chosenColors=''/>

以下是示例代码:

<mx:DataGridColumn dataField="@chosenColors" editorDataField="colors" headerText="Colors" width="200" wordWrap="true">
                    <mx:itemEditor>
                        <fx:Component>
                            <s:MXDataGridItemRenderer focusEnabled="true" height="22" >
                                <fx:Script>
                                    <![CDATA[
                                        public function get colors():String {
                                            var str:String = new String;
                                            for(var i:int=0;i < colorList.selectedItems.length; i++){
                                                if(i > 0){
                                                    str += ",\n";
                                                }
                                                str += colorList.selectedItems[i].@label;

                                            }
                                            return str;
                                        }
                                    ]]>
                                </fx:Script>
                                <r:CheckList id="colorList"
                                                    dataProvider="{parentApplication.colors}"
                                                    labelField="@label" width="100%" height="150"/>
                            </s:MXDataGridItemRenderer>
                        </fx:Component>
                    </mx:itemEditor>
                </mx:DataGridColumn>

但是,如果选择绿色和红色,则只需用以下内容替换XML:

<colorData chosenColors=' Green, Red'/>

相反,我希望生成的XML为:

<colorData chosenColors=' 1, 3'/>

请让我知道如何实现这一点 - 内联渲染器与否,其他实现等。感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

试试这会对你有帮助。

不是从selectedItems获取标签文本,而是获取value属性值,如@value。现在变成<colorData chosenColors='1, 3'/>

public function get colors():String {

    var values:Array = [];

    for(var i:int=0;i < colorList.selectedItems.length; i++){       
        values.push(colorList.selectedItems[i].@value.toString()); //Note here
    }

    return values.toString();
}

1,3也在网格中显示。我不确定你对UI级别的期望。仍然如果你想在UI级别显示颜色如绿色,红色,但同时你需要存储它们各自节点的值。如果在XML中再创建一个属性,如

<colorData chosenColors='Green, Red' chosenValueColors='1,3' />. 

这里选择了用于显示目的的颜色和为数据库选择的ValueColors或用于其他事情。现在,您可以从XML中的属性chosenValueColors获得期望值。

基于评论

要实现您的要求,您需要在itemRenderer中使用override data getter/setter方法,或者您可以使用dataChange事件。

override public function get data():Object
{
    return super.data;
}

override public function set data(value:Object):void
{
    super.data = value;

    if(!value)
        return;

    var selectedValues:Array = value.@chosenColors.toString().split(","); //get selected value in array
    var selectedIndices:Vector.<int> = new Vector.<int>();

    for (var i:int = 0, len:int = colorList.dataProvider.length; i < len; i++) 
    {
        var color:XML = colorList.dataProvider[i] as XML;

        if(selectedValues.indexOf(color.@value.toString()) > -1)
            selectedIndices.push(i); //Store index of selected items
    }

    trace(selectedIndices.toString());

    colorList.selectedIndices = selectedIndices;
}

public function get colors():String {

    var values:Array = [];

    for(var i:int=0;i < colorList.selectedItems.length; i++){

        values.push(colorList.selectedItems[i].@value.toString());
    }

    return values.toString();
}

public function colorList_changeHandler(event:IndexChangeEvent):void
{
    data.@value = colors; //IMPORT Commit the selected value to dataProvider.
}

请注意,我们将提交值的更改事件监听到change="colorList_changeHandler(event)"

等数据提供者
 <r:CheckList id="colorList" change="colorList_changeHandler(event)"
            dataProvider="{parentApplication.colors}"
            labelField="@label" width="100%" height="150"/>

答案 1 :(得分:0)

(编辑:此实现存在Flex 4.11的问题,如果使用addItem,有时会更改数据提供者 - 这可以在Flex 4.12中修复,但我还没有测试过。请参阅下面的注释评论。)

我实际上实现了与Raja Jaganathan略有不同,但我相信他的回答也会有所帮助。以下是我如何实施此修复程序。

同样,希望在itemEditor完成后使用XML更新XML dataProvider而不仅仅是文本。我实现这个的方法是在这个URL上遵循Adobe的例子(Flex 4.6指南): Examples using MX item editors with the list-based controls

我使用内联itemEditor作为我的列表,类似于我原来的问题。不同之处在于我改为实现数据功能的覆盖(类似于Raja所做的)。在data函数中(在itemEdit开始时调用),我设置了我的数据,但也根据我的XML中列出的颜色设置了列表控件的selectedItems。这确保了列表控件显示了在用户交互之前已经选择的颜色。

接下来,在itemEdit的末尾,我修改了colors函数,在XML上设置了一个临时属性,该属性包含在列表中选择的ID。这确保了用户的选择(如果与原始版本不同)。

现在,这里是我努力奋斗的地方,Raja的答案可能会更好。在colors函数中,我只是将list控件中选定的XML添加到dataProvider XML中。事实证明这是非常有问题的,因为Flex不会在没有首先转义XML的情况下将XML存储到dataProvider,留下一堆符号和HTML编码的XML(即垃圾)。为了解决这个问题,我在datagrid上为itemEditEnd事件创建了一个监听器。这个监听器调用了一个函数 - 类似于Adobe的例子 - 它读取所选择的颜色ID并用Flex给我带来的编码XML垃圾替换为真正的XML。这个XML中最重要的是立即调用preventDefault()以防止覆盖我对数据提供者的所作所为。

做这些事情使我能够向用户提供可供选择的列表,然后在用户移动到数据网格中的不同单元格时向用户显示他们当前的选择。当用户选择永久保存对表的更改时,它还允许我存储这些选项以供以后检索。

编辑:在这一点下面是对如何实现不同于Adobe的例子的更深层次的解释。

修改editedItemEditor.data时,上面的Adobe链接存在一些问题。相反,我在数据网格中添加了一个itemEditEnd事件处理函数,如下所示:

<mx:DataGrid id="dataGridSvcTypeReasons" height="100%" width="100%" dataProvider="{dataProvider}" editable="true" itemEditEnd="dataGrid_itemEditEndHandler(event)">

在处理程序函数中,我操纵原始数据 - 而不是每个Adobe示例中的editedItemRenderer.data:

protected function dataGrid_itemEditEndHandler(event:DataGridEvent):void{

    if (event.reason == DataGridEventReason.CANCELLED){
        // Do not update cell.
        return;
    }

    event.preventDefault();

    var data:Object = dataProvider.getItemAt(event.rowIndex);

    // look to see if my list exists (if not, then this edit does not pertain to my list)
    if(event.currentTarget.itemEditorInstance.hasOwnProperty("myList")){
        var selectedItems:Vector.<Object>;

        selectedItems = event.currentTarget.itemEditorInstance.myList.selectedItems;

        delete data.colors;
        data.appendChild(<colors/>);

        if(selectedItems){
            for each(var item:XML in selectedItems){
                for(var i:int = 0; i < myList.dataProvider.length; i++){
                    if(myList.dataProvider[i].@value == item.@value){
                        data.colors.appendChild(new XML(myList.dataProvider[i]));
                        break;
                    }
                }
            }
        }
    }
}

此方法将避免因销毁Adobe示例中的editedItemRenderer而导致的GUI问题。