问题描述
我有一个 Flex 问题,这并不像一开始看起来那么简单.
I have a Flex question, which isn't as easy as it seems at first.
至少我从 1 周起就在苦苦挣扎.
At least I'm struggling since 1 week with it.
我准备了一个测试用例和一个截图.
I have prepared a test case and a screenshot.
问题是:如何将数据(重复来自服务器)合并到过滤后的 ArrayCollection 中?
截图:
TestCase.mxml(只需将其放入 Flash Builder 4.6 项目中):
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>
问题在于,当 ArrayCollection _data 被过滤时(因为设置了复选框偶数"),那么测试用例中的第二个循环(用于添加新项目)添加项目(35")一次又一次 - 因为它被过滤了,因此不可见.
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.
请不要将我发送到诸如 IViewCursor 或 ListCollectionView.localIndex - 因为我在过去一周已经阅读了很多.
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.
谢谢!
推荐答案
尝试操作ArrayCollection
的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
的建议:
And a couple of advices on using RadioButton
and RadioButtonGroup
:
- 不要使用点击事件来处理更改.这禁用了以其他方式管理按钮的可能性(例如从键盘).改用
change
. - 如果您使用
RadioButtonGroup
,最好参考group
而不是groupName
.它使您可以在编译时检查问题(想象一下组名中的一些错误印刷). - 不要根据标签检查选定的按钮.您可能会误打印标签名称或更改标签等,而编译器对此无能为力.
- 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 refergroup
rather thangroupName
. 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?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!