Infragistics WinGrid, Outlook GroupBy, and ProBindingSource

Posted by bheavican on 30-Apr-2010 10:02

Can anyone help me here.  I have a ultrawingrid with the Outlook GroupBy turned on.  I have created a temp-table, a query for the temp-tables data and bound the data to the grid using a probindingsource.  I have a button that deletes the record from the temp-table and re-opens the query.  The group by collections are now wrong.

Example:

Data before any changes

1,2,1,3,4

2,3,2,3,4

3,4,2,5,4

4,2,3,5,4

5,2,3,7,4

6,4,1,8,4

7,3,1,9,4

8,5,1,3,4

Grouped by second column

Group 2 (3 items)

  1,,1,3,4

  4,,3,5,4

  5,,3,7,4

Group 3 (2 items)

  2,,2,3,4

  7,,1,9,4

Group 4 (2 items)

  3,,2,5,4

  6,,1,8,4

Group 5 (1 item)

  8,,1,3,4

After deleting record "4,2,3,5,4" (second record in Group 2) and re-opening query

Group 2 (3 items)

  1,,1,3,4

  5,,3,7,4

  6,,1,8,4

Group 3 (2 items)

  2,,2,3,4

  8,,1,3,4

Group 4 (2 items)

  3,,2,5,4

  7,,1,9,4

Does anyone know what i'm doing wrong here?  Screen shots and code is attached.

Progress 10.2A02 Infragistics version 8.1.20081.2176

[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/Form1.cls.zip:236:177]

[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/Form1.resx.zip:237:178]

[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/Groupby-Screen-Shots.docx:550:0]

All Replies

Posted by Admin on 30-Apr-2010 14:01

Does invoking the RefreshAll() method on the ProBindingSource after deleting the row any difference?

Von meinem iPad gesendet

Posted by Håvard Danielsen on 01-May-2010 15:50

From what I can see in Infragstics fora this is likely expected behavior. (Note that I did not find any direct mentioning of delete, but group positions are not changed automatically when the underlying cell is changed.)

I may be wrong, so feel free to report it to Support or enter an enhancement request, but if this is expected then you are using the right RefreshSortPosition() method to deal with this, but your code is traversing the rows of UltraGrid:Rows collection which will return the top level of GroupBy rows if GroupBy rows             are being used.

You should get the expected behavior if you call RefreshSortPosition on the row that has the wrong record in it (because you deleted the record that the grid used to sort and group it).  You can get a collection of the rows on the band through the Band:GetRowEnumerator(). The code below shows how to traverse the list, but it also illustrates a problem since the resort will (can?) cause the MoveNext to throw an exception. It should work if you call it after the query has opened (with "ttTest" as parameter), but I woud try to find a way to avoid the exception. (copy the list, or use Band:ChildRow to get the first and the equivalent of a "next-sibling" method if it exists).

 method public void resortBand(bandKey as char):
      define variable enumerator as System.Collections.IEnumerator  no-undo.
      define variable gridRow as Infragistics.Win.UltraWinGrid.UltraGridRow  no-undo.     
      enumerator = ultraGrid1:DisplayLayout:Bands[bandKey]:GetRowEnumerator(Infragistics.Win.UltraWinGrid.GridRowType:DataRow):GetEnumerator().     
      do while enumerator:moveNext():
         gridRow = cast(enumerator:Current,Infragistics.Win.UltraWinGrid.UltraGridRow).
         gridRow:RefreshSortPosition().
      end.   
      catch e as System.InvalidOperationException :
         /* nothing - moveNext failed because we changed position */
      end catch.
  end method.  

If you know the deleted row's ordinal position in the grid you might use the Index property as follows:

method public void resortRow(bandKey as char,pos as int):
      define variable enumerator as System.Collections.IEnumerator  no-undo.
      define variable gridRow    as Infragistics.Win.UltraWinGrid.UltraGridRow  no-undo.
     
      enumerator = ultraGrid1:DisplayLayout:Bands[bandKey]:GetRowEnumerator(Infragistics.Win.UltraWinGrid.GridRowType:DataRow):GetEnumerator().     
      do while enumerator:moveNext():
         gridRow = cast(enumerator:Current,Infragistics.Win.UltraWinGrid.UltraGridRow).
         if gridrow:Index = pos then
         do:
            gridRow:RefreshSortPosition().
            return.
         end.  
      end.         
  end method.

Another alternative is to delete the row from the grid BEFORE the query is opened. The advantage of doing this before the grid has changed is that you only need to know the deleted row's position in the query and not the position in the grid. The following code expects the deleted query postion and uses the 0 based ListIndex to figure out which row to delete.

method public void rowDeleted(bandKey as char,pos as integer):
      define variable enumerator as System.Collections.IEnumerator  no-undo.
      define variable gridRow    as Infragistics.Win.UltraWinGrid.UltraGridRow  no-undo.
      enumerator = ultraGrid1:DisplayLayout:Bands[bandKey]:GetRowEnumerator(Infragistics.Win.UltraWinGrid.GridRowType:DataRow):GetEnumerator().
      do while enumerator:moveNext():
          gridRow = cast(enumerator:Current,Infragistics.Win.UltraWinGrid.UltraGridRow).
          if gridRow:ListIndex + 1 = pos then
          do:
              gridRow:Delete(no) no-error.
              return.
          end.   
      end.    
  end method.

Note that the row is in a bad state at this point, and any operations may cause record not avail errors. The no-error seems to deal with this. If you call this BEFORE the record delete you do not need the no-error, but it may be hard to recover if the record delete should fail.

----

Your code is of course a simplified sample, but my assumption is that the grid is not in charge of the delete.

Posted by bheavican on 03-May-2010 11:02

This did not appear to alter my results

Posted by bheavican on 03-May-2010 11:09

The first example worked with a little tweaking.  The RefreshSortPosition was throwing the exception, as noted, so I created a second copy of collection and instead of using the MoveNext I traversed through all of the rows and invoked RefreshSortPosition.  The expanded state of some of the groups were wrong after this so I also added code to get the expanded rows and after refreshing the sort I set the states back to expanded if the group still existed.  The code is neither optimized nor fully tested but it appears to be working.

    DEFINE VARIABLE enumerator AS System.Collections.IEnumerator                    NO-UNDO.

    DEFINE VARIABLE gridRow    AS Infragistics.Win.UltraWinGrid.UltraGridRow        NO-UNDO.

    DEFINE VARIABLE groupByRow AS Infragistics.Win.UltraWinGrid.UltraGridGroupByRow NO-UNDO.

   

    enumerator = ultraGrid1:DisplayLayout:Bands[0]:GetRowEnumerator(Infragistics.Win.UltraWinGrid.GridRowType:GroupByRow):GetEnumerator().

   

    DO WHILE enumerator:moveNext():

     

      groupByRow = CAST(enumerator:Current,Infragistics.Win.UltraWinGrid.UltraGridGroupByRow).

     

      IF VALID-OBJECT(groupByRow) AND

        groupByRow:Expanded = YES THEN

      DO:

        CREATE ttExpandedGroups.

        ASSIGN

          ttExpandedGroups.rowValue = groupByRow:Value.

      END.

    END.

   

    hQuery:query-open().

         

    enumerator = ultraGrid1:DisplayLayout:Bands[0]:GetRowEnumerator(Infragistics.Win.UltraWinGrid.GridRowType:DataRow):GetEnumerator().

         

    DO WHILE enumerator:moveNext():

     

      gridRow = CAST(enumerator:Current,Infragistics.Win.UltraWinGrid.UltraGridRow).

     

      IF VALID-OBJECT(gridRow) THEN

      DO:

        CREATE ttGridRow.

        ASSIGN

          ttGridRow.row = gridRow.

      END.

    END.

   

    FOR EACH ttGridRow EXCLUSIVE-LOCK:

   

      gridRow = CAST(ttGridRow.row,Infragistics.Win.UltraWinGrid.UltraGridRow).

      gridRow:RefreshSortPosition().

     

      DELETE ttGridRow.

           

    END.

   

    FOR EACH ttExpandedGroups EXCLUSIVE-LOCK:

      enumerator = ultraGrid1:DisplayLayout:Bands[0]:GetRowEnumerator(Infragistics.Win.UltraWinGrid.GridRowType:GroupByRow):GetEnumerator().

   

      DO WHILE enumerator:moveNext():

     

        groupByRow = CAST(enumerator:Current,Infragistics.Win.UltraWinGrid.UltraGridGroupByRow).

       

        OUTPUT TO j:\employee\bheavican\uom.txt APPEND.

        PUT UNFORMATTED ttExpandedGroups.rowValue:ToString() SKIP.

        OUTPUT CLOSE.

    

        IF VALID-OBJECT(groupByRow) AND

          Progress.Util.EnumHelper:Equals(groupByRow:Value,CAST(ttExpandedGroups.rowValue,System.Object)) AND

          groupByRow:IsExpanded = NO AND

          groupByRow:IsExpandable = YES THEN

          groupByRow:Expanded = YES.

      END.

     

      DELETE ttExpandedGroups.

    END.

This thread is closed