0

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

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

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

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

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

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

这应该通过以下 datagridcolumn (CheckList 只是一个允许在不按住 CTRL 键的情况下进行多项选择的列表)使用该列的给定数据提供程序自然识别:

<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>

但是,如果选择了 Green 和 Red,则这只是将 XML 替换为以下内容:

<colorData chosenColors=' Green, Red'/>

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

<colorData chosenColors=' 1, 3'/>

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

4

2 回答 2

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' />. 

这里 selectedColors 用于显示目的,并且 selectedValueColors 用于可能数据库或用于其他事情。现在您可以从 XML 中的属性 selectedValueColors 中获得预期值。

根据评论

为了满足您的要求,您需要override data getter/setter在 itemRenderer 中使用方法,或者您可以使用 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"/>
于 2014-03-10T06:35:10.147 回答
0

(编辑:此实现在 Flex 4.11 中存在问题,如果使用 addItem,有时会更改数据提供者 - 这可能在 Flex 4.12 中修复,但我尚未测试。请参阅下面的评论以获取解决方案。)

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

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

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

接下来,在 itemEdit 结束时,我修改了我的颜色函数以在 XML 上设置一个临时属性,该属性包含在列表中选择的 ID。这确保了用户的选择(如果与原始选择不同)被捕获。

现在,这是我挣扎的地方,而拉贾的答案可能会更好。在颜色函数中,我只是将列表控件中选定的 XML 添加到 dataProvider XML 中。事实证明这是非常有问题的,因为 Flex 不会将 XML 存储到 dataProvider 而不首先对其进行转义,从而留下一堆 & 符号和 HTML 编码的 XML(即垃圾)。为了解决这个问题,我在数据网格上为 itemEditEnd 事件创建了一个侦听器。这个监听器调用了一个函数——类似于 Adob​​e 的例子——读取选择的颜色 id 并用真正的 XML 替换 Flex 给我的编码 XML 垃圾。此 XML 中最重要的事情是立即调用 preventDefault() 以防止覆盖我对数据提供者所做的操作。

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

编辑:在这一点下面是对如何以不同于 Adob​​e 示例的方式实现的更深入的解释。

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

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

在处理程序函数中,我操作了原始数据——而不是按照 Adob​​e 的示例编辑的ItemRenderer.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;
                    }
                }
            }
        }
    }
}

此方法将避免由于破坏 Adob​​e 示例中的已编辑项目渲染器而导致的 GUI 问题。

于 2014-03-11T13:48:59.120 回答