1 Reply Latest reply on Jan 8, 2010 1:55 PM by Flex harUI

    Replacing rows in DataGrid using ArrayCollection as a data source?

    klopus-normalis

      I have a DataGrid that uses ArrayCollection as a data source. ArrayCollection itself is updated from raw data messages coming from Consumer. Each message represents a row to be displayed in a DataGrid. Message body is an associative array of {fieldName:value} pairs. Field with the name "Id" contains a unique record index (fixed size string).

       

      Records with Id that's not yet present in data source should be simpy added to the DataGrid. But if given Id already exists new record should replace the existing one with DataGrid reflecting the change. I poked around a came up with the following solution:

       

         <mx:Script>
              <![CDATA[
                  /** Array to accumulate messages as a data provider for the data grid */       
                  [Bindable] private var _items:ArrayCollection = new ArrayCollection()


                  /** Iterator over data items collection */
                  private var _cursor:IViewCursor
                 
                  /** First thing to run */
                  private function main():void {
                      // define a sorted (by Id) cursor on a data source to do record find operations
                      var sorter:Sort = new Sort()
                      sorter.fields = [new SortField("Id", true)] // not case sensitive
                      _items.sort = sorter
                      _items.refresh()
                      _cursor = _items.createCursor()
                  }
                 
                  /** Accept messages from the Consumer */
                  private function messageHandler(event:MessageEvent):void {
                      // find record by Id and replace it with the new version, otherwise just add a new record to the end
                      var criteria:Object = {Id: event.message.body.Id}
                      if (_cursor.findAny(criteria)) {
                          _cursor.remove()
                          _cursor.insert(event.message.body)
                      }
                      else {
                          _items.addItem(event.message.body)
                      }
                  }

              ]]>
          </mx:Script>
         
          <!-- Define message Consumer -->
          <mx:Consumer id="consumer"
              destination="pubtool-test"
              message="messageHandler(event)"
               fault="faultHandler('Consume', event)"
           />
          
          <!-- Gui part -->
         
          <mx:HBox>
              <mx:Button label="Start" click="consumer.subscribe()" id="btnStart"/>
              <mx:Button label="Stop"  click="consumer.unsubscribe()"  id="btnStop"/>
          </mx:HBox>
         
          <mx:DataGrid dataProvider="{_items}" width="100%" height="100%" borderStyle="outset"/>

       

      It works but is it the right and most efficient approach? Moreover it works only when user doesn't click some other than "Id" column to sort. In typical MVC fashion users should be able to sort the View (DataGrid) but replacing record in the Model (ArrayCollection) shouldn't affect the View. Unfortunately with soultion above it does. For such a simple and typical thing I would hate to implement an intermediate IViewCollection and link it by events to the DataGrid source collection. I'm new to AS and my prior experience is with Java Swing and C# where with typical grid controls and data models replacing a row by unique index isn't a problem. Please advise.

       

      Thanks.