将数据合并到过滤的ArrayCollection中(可能使用IViewCursor或localIndex?)

时间:2012-01-05 02:06:06

标签: flex collections flex4 flex4.5 arraycollection

我有一个Flex问题,这并不像最初看起来那么容易。

至少我从一周开始就挣扎着。

我准备了一个测试用例和截图。

问题是:如何将数据(从服务器反复出现)合并到过滤后的ArrayCollection中?

截图:

screenshot

TestCase.mxml(只需将其放入Flash Builder 4.6项目中):

<?xml version="1.0" encoding="utf-8"?>
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Declarations>
        <s:RadioButtonGroup id="_group" itemClick="radioClicked(event);"/>
    </fx:Declarations>

    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.events.ItemClickEvent;

            [Bindable]
            private var _data:ArrayCollection = new ArrayCollection();

            private const DATA1:Array = [10,20,30,40,50]; 
            private const DATA2:Array = [10,20,30,50]; 
            private const DATA3:Array = [10,20,30,40,50,60]; 
            private const DATA4:Array = [10,20,30,35,40,50]; 
            private const DATA5:Array = [];
            private const DATA6:Array = [25,45]; 

            private function merge(data:Array):void {
                var i:int;
                var j:int;

                // 1) remove items missing in data from _data
                found1:
                for (i = _data.length - 1; i >= 0; i--) {
                    for (j = data.length - 1; j >= 0; j--) {
                        if (_data[i] == data[j])
                            continue found1;
                    }
                    _data.removeItemAt(i);
                }

                // 2) add items appeared in data to _data
                found2:
                for (j = 0; j < data.length; j++) {
                    for (i = 0; i < _data.length; i++) {
                        if (_data[i] == data[j])
                            continue found2;
                    }
                    _data.addItem(data[j]);
                }
            }

            private function radioClicked(event:ItemClickEvent):void {
                if (event.label.indexOf('Odd') == 0) {
                    _data.filterFunction = filterOdd; 
                } else if (event.label.indexOf('Even') == 0) {
                    _data.filterFunction = filterEven; 
                } else {
                    _data.filterFunction = null; 
                }
                _data.refresh();
            }

            private function filterOdd(item:Object):Boolean {
                var i:uint = item as uint;
                return (i % 2 == 1);
            }

            private function filterEven(item:Object):Boolean {
                var i:uint = item as uint;
                return (i % 2 == 0);
            }
        ]]>
    </fx:Script>

    <s:layout>
        <s:VerticalLayout gap="20" />
    </s:layout>

    <s:HGroup verticalAlign="baseline">
        <s:Label text="FILTER:" />
        <s:RadioButton groupName="_group" label="All" selected="true" />
        <s:RadioButton groupName="_group" label="Odd" />
        <s:RadioButton groupName="_group" label="Even" />
    </s:HGroup>

    <s:List id="_list" dataProvider="{_data}" />

    <s:Button id="_btn1" label="{DATA1.join()}" click="merge(DATA1)" />
    <s:Button id="_btn2" label="{DATA2.join()}" click="merge(DATA2)" />
    <s:Button id="_btn3" label="{DATA3.join()}" click="merge(DATA3)" />
    <s:Button id="_btn4" label="{DATA4.join()}" click="merge(DATA4)" />
    <s:Button id="_btn5" label="{DATA5.join()}" click="merge(DATA5)" />
    <s:Button id="_btn6" label="{DATA6.join()}" click="merge(DATA6)" />

</s:Application>

问题在于,当ArrayCollection _data 过滤(因为设置了Checkbox“Even”)时,测试用例中的第二个循环(用于添加新项目)添加项目(“35”)一次又一次 - 因为它已被过滤,因此不可见

请使用源代码建议解决方案。

请不要将我发送给IViewCursorListCollectionView.localIndex等文档,因为我已经在过去一周内阅读过很多文档。

谢谢!

1 个答案:

答案 0 :(得分:2)

尝试按以下方式操作ArrayCollection的{​​{1}}媒体资源:

source

关于使用<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"> <fx:Declarations> <s:RadioButtonGroup id="filterGroup" change="radioClicked(event)" /> </fx:Declarations> <fx:Script> <![CDATA[ import mx.collections.ArrayCollection; private const DATA1:Array = [ 10, 20, 30, 40, 50 ]; private const DATA2:Array = [ 10, 20, 30, 50 ]; private const DATA3:Array = [ 10, 20, 30, 40, 50, 60 ]; private const DATA4:Array = [ 10, 20, 30, 35, 40, 50 ]; private const DATA5:Array = []; private const DATA6:Array = [ 25, 45 ]; [Bindable] private var _data:ArrayCollection = new ArrayCollection(); private function filterEven(item:Object):Boolean { var i:uint = item as uint; return (i % 2 == 0); } private function filterOdd(item:Object):Boolean { var i:uint = item as uint; return (i % 2 == 1); } private function merge(data:Array):void { var i:int; var j:int; var sourceData:Array = _data.source; // 1) remove items missing in data from _data found1: for (i = sourceData.length - 1; i >= 0; i--) { for (j = data.length - 1; j >= 0; j--) { if (sourceData[i] == data[j]) continue found1; } var index:int = _data.getItemIndex(sourceData[i]); if (index > -1) _data.removeItemAt(index); // remove visible items else sourceData.splice(i, 1); // remove hidden (filtered) items } // 2) add items appeared in data to _data found2: for (j = 0; j < data.length; j++) { for (i = 0; i < sourceData.length; i++) { if (sourceData[i] == data[j]) continue found2; } _data.addItem(data[j]); } } private function radioClicked(event:Event):void { switch (filterGroup.selection) { case allButton: { _data.filterFunction = null; break; } case oddButton: { _data.filterFunction = filterOdd; break; } case evenButton: { _data.filterFunction = filterEven; break; } } _data.refresh(); } ]]> </fx:Script> <s:layout> <s:VerticalLayout gap="20" /> </s:layout> <s:HGroup verticalAlign="baseline"> <s:Label text="FILTER:" /> <s:RadioButton id="allButton" group="{filterGroup}" label="All" selected="true" /> <s:RadioButton id="oddButton" group="{filterGroup}" label="Odd" /> <s:RadioButton id="evenButton" group="{filterGroup}" label="Even" /> </s:HGroup> <s:List dataProvider="{_data}" id="_list" /> <s:Button click="merge(DATA1)" id="_btn1" label="{DATA1.join()}" /> <s:Button click="merge(DATA2)" id="_btn2" label="{DATA2.join()}" /> <s:Button click="merge(DATA3)" id="_btn3" label="{DATA3.join()}" /> <s:Button click="merge(DATA4)" id="_btn4" label="{DATA4.join()}" /> <s:Button click="merge(DATA5)" id="_btn5" label="{DATA5.join()}" /> <s:Button click="merge(DATA6)" id="_btn6" label="{DATA6.join()}" /> </s:Application> RadioButton的一些建议:

  • 请勿使用点击事件来处理更改。这会禁用以其他方式管理按钮的可能性(例如,从键盘)。请改用RadioButtonGroup
  • 如果您使用change,最好引用RadioButtonGroup而不是group。它使您可以在编译时检查问题(想象一下组名中的一些错误印记)。
  • 请勿针对标签检查所选按钮。您可能会错误打印标签名称,或者您可以更改标签等。编译器无法帮助您。