11 Replies Latest reply on Nov 10, 2011 10:37 AM by Brian_ONE

    DataGrid selectedIndex and highlighting do not match after sort

    REM018

      Hi,

       

      I am experiencing difficulties with the  selectedItem/selectedIndex after I sort my data in a DataGrid. Let' say  the data looks like this and row 2 is highlighted in the grid  (selected):

       

      Col 1          Col 2               Col 3   

      1               Test               Test 3

      2               Test                Test 1

      3               Test                Test 2

      4               Test                Test 4

       


      Now  let's say I sort by Col 3, ascending, by clicking on the column header.  The visual result is this (which is correct):

       

      Col 1          Col 2               Col  3   

      2               Test                Test 1

      3               Test                Test 2

      1                Test               Test 3

      4               Test                Test 4

       

      The problem is: If I click on the new row 2, then nothing  happens. It does not change visual selection nor does it trigger the  selection change event or anything.

       

      As far as I understand it, the grid still thinks that  selectedIndex = 1, even though it should be 0, which is what the  highlighting indicates. Clicking on any other row than 2 works fine.

       

      I can not really find a reason for that or a workaround  since there does not seem to be an event that can be caught once all the  sorting is done. I can catch header_release, but that happens before  the sort is executed. And to me it seems like I should not be catching  anything here anyways since that it is a pretty basic operation that  should be handled by the DataGrid without intervention.

       

      My data of course is more complicated than that and I am  using custom objects and hierarchical data as a dataprovider, with a  different rendererProvider for the nested data. It just seems weird to  me that the highlighting would still work, but the selectedIndex does  not change. But if I use the selectedItem to do something with it, it  points to the currently highlighted item.

       

      I also tried it with another DataGrid with a simpler data  source and that also had issues with highlighting and selectedIndex  being out-of-sync.

       

      I am really confused about that and would appreciate any  pointers. I can also post more details if required.

       

      Thanks!

        • 1. Re: DataGrid selectedIndex and highlighting do not match after sort
          Flex harUI Adobe Employee

          Try a simpler test case and see if you have the same problem.

          • 2. Re: DataGrid selectedIndex and highlighting do not match after sort
            VRPDeveloper Level 3

            I think you are missing something. You need to refresh dataprovider.

            See the code below.  Hope it will help you.

             

            <?xml version="1.0"?>
            <!-- dpcontrols/DataGridSort.mxml -->
            <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                  initialize="initDP();" width="550" height="400">
                 
               <mx:Script>
                  <![CDATA[
                     import mx.events.DataGridEvent;
                     import mx.collections.*;
                    
                     // Declare storage variables and initialize the simple variables.
                     // The data provider collection.
                     private var myDPColl:ArrayCollection;
                     // The Sort object used to sort the collection.
                     [Bindable]
                     private var sortA:Sort;
                     // The sort fields used to determine the sort.
                      private var sortByInStock:SortField;
                      private var sortByArtist:SortField;
                      private var sortByAlbum:SortField;
                      private var sortByPrice:SortField;
                     // The data source that populates the collection.
                     private var myDP:Array = [
                        {Artist:'Pavement', Album:'Slanted and Enchanted',
                           Price:11.99, InStock: true},
                        {Artist:'Pavement', Album:'Crooked Rain, Crooked Rain',
                           Price:10.99, InStock: false},
                        {Artist:'Pavement', Album:'Wowee Zowee',
                           Price:12.99, InStock: true},
                        {Artist:'Asphalt', Album:'Brighten the Corners',
                           Price:11.99, InStock: false},
                        {Artist:'Asphalt', Album:'Terror Twilight',
                           Price:11.99, InStock: true},
                        {Artist:'Asphalt', Album:'Buildings Meet the Sky',
                           Price:14.99, InStock: true},
                        {Artist:'Other', Album:'Other', Price:5.99, InStock: true}
                     ];

                     //Initialize the DataGrid control with sorted data.
                     private function initDP():void {
                        //Create an ArrayCollection backed by the myDP array of data.
                        myDPColl = new ArrayCollection(myDP);
                        //Create a Sort object to sort the ArrrayCollection.
                        sortA = new Sort();
                        //Initialize SortField objects for all valid sort fields:
                        // A true second parameter specifies a case-insensitive sort.
                        // A true third parameter specifies descending sort order.
                        // A true fourth parameter specifies a numeric sort.
                         sortByInStock = new SortField("InStock", true, true);
                         sortByArtist = new SortField("Artist", true);
                         sortByAlbum = new SortField("Album", true);
                         sortByPrice = new SortField("Price", true, false, true);
                        // Sort the grid using the InStock, Artist, and Album fields.
                        sortA.fields=[sortByInStock, sortByArtist, sortByAlbum];
                        myDPColl.sort=sortA;
                        // Refresh the collection view to show the sort.
                        myDPColl.refresh();
                        // Initial display of sort fields
                        tSort0.text = "First Sort Field: InStock";
                        tSort1.text = "Second Sort Field: Artist";
                        tSort2.text = "Third Sort Field: Album";

                        // Set the ArrayCollection as the DataGrid data provider.
                        myGrid.dataProvider=myDPColl;
                        // Set the DataGrid row count to the array length,
                        // plus one for the header.
                        myGrid.rowCount=myDPColl.length +1;
                     } 
                 
                     // Re-sort the DataGrid control when the user clicks a header.
                     private function headRelEvt(event:DataGridEvent):void {
                        // The new third priority was the old second priority.
                        sortA.fields[2] = sortA.fields[1];
                        tSort2.text = "Third Sort Field: " + sortA.fields[2].name;
                        // The new second priority was the old first priority.
                        sortA.fields[1] = sortA.fields[0];
                        tSort1.text = "Second Sort Field: " + sortA.fields[1].name;
                        // The clicked column determines the new first priority.
                        if (event.columnIndex==0) {
                           sortA.fields[0] = sortByArtist;
                        } else if (event.columnIndex==1) {
                           sortA.fields[0] = sortByAlbum;
                        } else if (event.columnIndex==2) {
                           sortA.fields[0] = sortByPrice;
                        } else {
                           sortA.fields[0] = sortByInStock;}
                        tSort0.text = "First Sort Field: " + sortA.fields[0].name;
                        // Apply the updated sort fields and re-sort.
                        myDPColl.sort=sortA;
                        // Refresh the collection to show the sort in the grid.
                        myDPColl.refresh();
                        // Prevent the DataGrid from doing a default column sort.
                        event.preventDefault();
                     }
                  ]]>
               </mx:Script>

               <!-- The Data Grid control.
                     By default the grid and its columns can be sorted by clicking.
                     The headerRelease event handler overrides the default sort
                     behavior. -->
               <mx:DataGrid id="myGrid" width="100%" headerRelease="headRelEvt(event);">
                  <mx:columns>
                        <mx:DataGridColumn minWidth="120" dataField="Artist" />
                        <mx:DataGridColumn minWidth="200" dataField="Album" />
                        <mx:DataGridColumn width="75" dataField="Price" />
                        <mx:DataGridColumn width="75" dataField="InStock"
                           headerText="In Stock"/>
                  </mx:columns>
               </mx:DataGrid>
               <mx:VBox>
                  <mx:Label id="tSort0" text="First Sort Field: "/>
                  <mx:Label id="tSort1" text="Second Sort Field: "/>
                  <mx:Label id="tSort2" text="Third Sort Field: "/>
               </mx:VBox>
            </mx:Application>
            • 3. Re: DataGrid selectedIndex and highlighting do not match after sort
              REM018 Level 1

              Thanks for the suggestion. But I do not want to re-implement the sorting myself. I would expect the

              grid to handle the sorting itself. It might come down to this as a workaround, but I do not like the idea of having to that.

               

              I created a very simple project that illustrates the problem. It seems to be related to using HierarchialData as data provider for the grid. If I remove it and make the ArrayCollection the data provider, then sorting works fine.

               

              To try: Just add the files to a new project, launch and click on one row, sort by any column and make the selected row move to a different position and then try to select the row that is at the previous position of the selected row.

               

              I am using Flex 3.4.

               

              Here is my test object:

               

              package
              {
                  [Bindable]
                  public class TestObject
                  {
                      protected var myId:int = -1;
                      protected var myName:String = "";
                     
                      public function get id():int{
                          return myId;
                      }
                      public function set id(val:int):void{
                          myId = val;
                      }
                      public function get name():String{
                          return myName;
                      }   
                      public function set name(param:String):void{
                          myName = param;           
                      }   
                  }
              }

               

              And here is the application:

              <?xml version="1.0" encoding="utf-8"?>
              <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
                  <mx:Script>
                      <![CDATA[
                          import mx.collections.ArrayCollection;
                          [Bindable]
                          protected var gridData:ArrayCollection = null;
                         
                          protected function handleInit(event:Event):void{
                              gridData = new ArrayCollection();
                              var ta:TestObject = new TestObject();
                              ta.id = 1;
                              ta.name = "Test 1";
                              gridData.addItem(ta);
                              ta = new TestObject();
                              ta.id = 2;
                              ta.name = "Test 2";
                              gridData.addItem(ta);
                              ta = new TestObject();
                              ta.id = 3;
                              ta.name = "Test 4";
                              gridData.addItem(ta);
                              ta = new TestObject();
                              ta.id = 5;
                              ta.name = "Test 5";
                              gridData.addItem(ta);
                          }
                      ]]>
                  </mx:Script>
                  <mx:AdvancedDataGrid id="grid"
                      width="100%" height="100%"
                      sortExpertMode="true"
                      initialize="handleInit(event)">
                      <mx:dataProvider>
                          <mx:HierarchicalData source="{gridData}" />           
                      </mx:dataProvider>
                      <mx:columns>
                          <mx:AdvancedDataGridColumn dataField="id" headerText="Id" />
                          <mx:AdvancedDataGridColumn dataField="name" headerText="Name" />
                      </mx:columns>
                  </mx:AdvancedDataGrid>
              </mx:Application>

              • 4. Re: DataGrid selectedIndex and highlighting do not match after sort
                REM018 Level 1

                I tried the provided example in a Flex 4 environment and the same behavior could be observed.

                 

                I would really appreciate it if somebody could run that example code I provided (takes 5 minutes) and tell me whether I am doing something wrong here or if that is a shortcoming of the SDK.

                • 5. Re: DataGrid selectedIndex and highlighting do not match after sort
                  rtalton Level 4

                  I tried the example and got the same results in FB3.

                  The selectedIndex remains the same after a sort so when you click on the former position of the item you selected prior to a sort, the selectedItem highlighted in the grid does not change. The AdvancedDataGrid thinks you are still clicking on the same selectedIndex (you are), so the highlight does not change. Something in this class must not be updating the selectedItem properly, so I came up with a work-around for you.

                   

                  Create an event handler for the Grid's itemClick event, then do this:

                   

                   

                  private function handleItemClick(event:ListEvent):void{

                   

                       this.grid.selectedItem = event.itemRenderer.data;

                  }

                   

                  This will explicitly set the highlight for you.

                  I haven't tested this under all circumstances. If you are doing a multiple-column sort, you'd have to instead use selectedIndices somehow.

                   

                  1 person found this helpful
                  • 6. Re: DataGrid selectedIndex and highlighting do not match after sort
                    REM018 Level 1

                    Hi rtalton,

                     

                    thanks for the suggestion. In your post you are indicating that something is wrong with updating the selectedItem and the selectedIndex is correct. But to me it seems as if the selectedIndex does not get updated properly, but the selectedItem does (or at least the highlighting).

                     

                    After the sort, I would expect the previously selected entry to remain the selected entry (index and item). But it seems that the index is not being updated properly and still pointing to the old location of the selected row, which is not correct IMO.

                     

                    I tried listening to the data providers change event and resetting the selectedIndex there, but that one is being called very often and not related to sort only (obviously). That lead to more problems than it helped so far.

                     

                    I am still not sure how to work around this.

                    • 7. Re: DataGrid selectedIndex and highlighting do not match after sort
                      Flex harUI Adobe Employee

                      You may be running into the issue that sorting of heirarchical data is not

                      well-defined in ADG, although I wouldn't expect the results you are getting

                      either.

                       

                      DG and ADG only support simple application of a Sort object to a single

                      collection.  Hierarchical data is really a tree of collections and the sort

                      APIs are not robust enough to allow you to specify how the sort should

                      behave on the tree.

                      • 8. Re: DataGrid selectedIndex and highlighting do not match after sort
                        rootsounds Level 4

                        Yeah...things get a little funky once you start trying to customize the behavior of some of the Flex controls. In this case, i recommend avoiding the use of selectedIndex since the indicies will of course change on a sort. Item references however will not change until the data provider receives a fresh object (obviously it's not doing anything behind the scenes to associate selectedIndex values with the actual item references). If need be, you try storing a collection of references to the selected items prior to the sort and restore them after the sort.

                        1 person found this helpful
                        • 9. Re: DataGrid selectedIndex and highlighting do not match after sort
                          rtalton Level 4

                          At least I now know "it's not just me".

                          I had lots of difficulty with the ADG on a recent project. Got it working pretty nicely with custom group renderers & disclosure icons, item renderers, lots of formatting, etc. but it was a lot of work and as it ended up we scrapped it for other reasons. But it was a painful introduction to the ADG and using heirarchical data. A good component, but very difficult to customize. Just sayin'.

                           

                          As a work-around to this issue, I would go with the itemClick event method I wrote in my last post since that is not getting triggered often enough to be objectionable, I think.

                           

                          Thanks for the clarification Alex.

                          • 10. Re: DataGrid selectedIndex and highlighting do not match after sort
                            REM018 Level 1

                            I finally found a solution that I can live with. Please let me know if you see any issues with that approach.

                             

                            My main problem was that I did not find any event that notifies me about when sorting is done. But since my component is derived from AdvancedDataGrid, I am now just overriding the grid's sortHandler function, which is handling the sorting and only exits after the sorting is done.After that, I am just refreshing the selectedItem(s) to make the grid update itself properly.

                             

                            Sample code:

                             

                             

                            override protected function sortHandler(event:AdvancedDataGridEvent):void{

                                 super.sortHandler(event);

                                 // Store what is currently selected (selectedItem is correct, selectedIndex is wrong)

                                 var selItem:Object = this.selectedItem;

                                 var selItems:Array = this.selItems;

                                 // Clear the selection

                                 this.selectedItem = null;

                                 // Reset the selection

                                 this.selectedItem = selItem;

                                 this.selectedItems = selItems;

                            }

                             

                             

                            This works for me so far. If anybody knows a more elegant way, please let me know.

                            • 11. Re: DataGrid selectedIndex and highlighting do not match after sort
                              Brian_ONE

                              I also encountered the same issue, and also came up with the approach to reset the selectedItem & selectedItems.  But it causes a spike in CPU doing this for large grid.  I have a very large grid (thousands of rows) where I may be updating the rows, which may cause re-ordering of the rows.  And I get the situation where the selection doesn't match the selectedIndex - so that the user clicks on unselected row, and nothing happens because the grid thinks it is selected, but it's not, so nothing happens.

                               

                              I still have not come up with a good solution to this BUG BUG BUG!!!  I think I am going to submit to Adobe now.