合并数据到过滤的ArrayCollection(也许通过使用IViewCursor或localIndex?) [英] Merge data into filtered ArrayCollection (maybe by using IViewCursor or localIndex?)

查看:291
本文介绍了合并数据到过滤的ArrayCollection(也许通过使用IViewCursor或localIndex?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



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

至少我从那以来一直在努力。 p>

我已经准备了测试用例和截图。



问题是: (从服务器重复发送)到过滤的ArrayCollection?



屏幕截图:





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

 <?xml version =1.0encoding =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 =_ groupitemClick =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];

私人函数merge(data:Array):void {
var i:int;
var j:int;

// 1)从_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)将出现在数据中的项目添加到_data
found2:
for(j = 0; 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();
}

私人函数filterOdd(item:Object):Boolean {
var i:uint = item as uint;
return(i%2 == 1);
}

私有函数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 =_ grouplabel =Allselected =true/>
< s:RadioButton groupName =_ grouplabel =Odd/>
< s:RadioButton groupName =_ grouplabel =Even/>
< / s:HGroup>

< s:List id =_ listdataProvider ={_ data}/>

< s:Button id =_ btn1label ={DATA1.join()}click =merge(DATA1)/>
< s:Button id =_ btn2label ={DATA2.join()}click =merge(DATA2)/>
< s:Button id =_ btn3label ={DATA3.join()}click =merge(DATA3)/>
< s:Button id =_ btn4label ={DATA4.join()}click =merge(DATA4)/>
< s:Button id =_ btn5label ={DATA5.join()}click =merge(DATA5)/>
< s:Button id =_ btn6label ={DATA6.join()}click =merge(DATA6)/>

< / s:Application>

问题在于当ArrayCollection _data 过滤 (因为复选框Even已设置),则测试用例中的第二个循环(用于添加新项目)会一次又一次添加项目(35),因为它已过滤,因此不可见



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



请不要将我发送到文档 IViewCursor ListCollectionView.localIndex - 因为我



谢谢!

解决方案

尝试以下列方式操作 ArrayCollection 资源属性:

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

< fx:Declarations>
< s:RadioButtonGroup id =filterGroupchange =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();

私有函数filterEven(item:Object):Boolean
{
var i:uint = item as uint;
return(i%2 == 0);
}

私人函数filterOdd(item:Object):Boolean
{
var i:uint = item as uint;
return(i%2 == 1);
}

私有函数merge(data:Array):void
{
var i:int;
var j:int;


var sourceData:Array = _data.source;
// 1)从_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); //删除隐藏的(过滤的)项目
}

// 2)将出现在数据中的项目添加到_data
found2:for(j = 0; j< data.length ; j ++)
{
for(i = 0; 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 =allButtongroup ={filterGroup}label =Allselected =true/>
< s:RadioButton id =oddButtongroup ={filterGroup}label =Odd/>
< s:RadioButton id =evenButtongroup ={filterGroup}label =Even/>
< / s:HGroup>

< s:List dataProvider ={_ data}id =_ list/>

< s:Button click =merge(DATA1)id =_ btn1label ={DATA1.join()}/>
< s:Button click =merge(DATA2)id =_ btn2label ={DATA2.join()}/>
< s:Button click =merge(DATA3)id =_ btn3label ={DATA3.join()}/>
< s:Button click =merge(DATA4)id =_ btn4label ={DATA4.join()}/>
< s:Button click =merge(DATA5)id =_ btn5label ={DATA5.join()}/>
< s:Button click =merge(DATA6)id =_ btn6label ={DATA6.join()}/>

< / s:Application>

还有一些关于使用 RadioButton的建议 RadioButtonGroup




  • 不要使用点击事件来处理更改。这将禁止以其他方式管理按钮的可能性(例如,从键盘)。 c> 请参阅 group ,而不是 groupName 。它可以检查编译时的问题(想象组名中有些错字)。

  • 不要选中标签上的选定按钮。您可以压印标签名称,也可以更改标签等,编译器无法帮助您。


I have a Flex question, which isn't as easy as it seems at first.

At least I'm struggling since 1 week with it.

I have prepared a test case and a screenshot.

The question is: how do you merge data (coming repeatedly from server) into a filtered ArrayCollection?

The screenshot:

The TestCase.mxml (just place it into a Flash Builder 4.6 project):

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

The problem lies in the fact, that when the ArrayCollection _data is filtered (because the Checkbox "Even" is set), then the 2nd loop in the test case (for adding new items) adds items (the "35") again and again - because it's filtered and thus not visible.

Please suggest a solution - with the source code.

Please do not send me to docs like IViewCursor or ListCollectionView.localIndex - because I've read a lot of them in the past week already.

Thank you!

解决方案

Try to operate ArrayCollection's source property the following way:

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

And a couple of advices on using RadioButton and RadioButtonGroup:

  • Do not use click events to handle changes. This disables possibility to manage buttons other way (from keyboard for example). Use change instead.
  • If you are using RadioButtonGroup it is better to refer group rather than groupName. It gives you possibility to check problems on compile time (imagine some misprints in group name).
  • Do not check selected button against label. You can misprint label name or you can change label etc. and compiler can't help you in that.

这篇关于合并数据到过滤的ArrayCollection(也许通过使用IViewCursor或localIndex?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆