2012-01-05 2 views
1

У меня вопрос Flex, который не так прост, как кажется на первый взгляд.Объединить данные в фильтр ArrayCollection (возможно, с помощью IViewCursor или localIndex?)

По крайней мере, я боюсь с 1 недели с этим.

Я подготовил кейс и скриншот.

Вопрос: Как вы объедините данные (поступающие повторно с сервера) в отфильтрованный ArrayCollection?

Скриншот:

screenshot

TestCase.mxml (просто поместите его в 4.6 проекта Flash Builder):

<?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») потому что он фильтруется и, следовательно, не отображается.

Пожалуйста, предложите решение - с исходным кодом.

Пожалуйста, не отправляйте меня в такие документы, как IViewCursor или ListCollectionView.localIndex - потому что я прочитал их много на прошлой неделе.

Спасибо!

ответ

2

Попробуйте управлять ArrayCollection «s 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, а не groupName. Это дает вам возможность проверять проблемы во время компиляции (представьте некоторые опечатки в имени группы).
  • Не проверять выбранную кнопку на этикетке. Вы можете опечатать имя ярлыка, или вы можете изменить ярлык и т. Д., И компилятор в этом не поможет.
+0

Прекрасный ответ, спасибо. Мне просто интересно, если getItemIndex() всегда будет работать даже для более сложных объектов, хранящихся в ArrayCollection? –

+0

Насколько ActionScript работает с указателями на объекты, все указатели на один и тот же экземпляр равны. И 'ArrayCollection' просто сравнивает указатели на экземпляры сложных типов в' getItemIndex() '. Таким образом, он отлично подходит для сложных объектов. – Constantiner

+0

Итак, если у меня есть ArrayCollection объектов XML в моем реальном приложении и вам нужно сравнить и