Hi,
I have run into a significant performance issue with our grid under heavy load testing, with our particular design. (I saw your million row example with a single band, which loaded instantly, so I assume there is a way to improve this issue; but that example was not really the same as this.)
For a 10,000 row grid, the initial grid loads in about a minute or less, which is acceptable. BUT THEN when I right-click a row, another 8 minutes goes by before the context menu appears. Adding some debug, it appears to be looping through FilterRow events for every single child row of every single row in the grid at this time, as opposed to only looking at the children of the row that was clicked.
Am wondering if there is an appropriate way to handle the issue via disabling events, different events used, somehow force-tell it to look only at the band immediately under the band clicked, etc.
EXAMPLE:
We have an ultragrid which loads linked data from two table. Customers and Orders (not really, but for the sake of example.)
There might be 50,000 customers.
For each Customer, there might be 1 to 50 orders.
(in my actual test, I had 10,000 rows, but the above numbers are realistic.)
Since I want a parent band / child band relationship between the two, I add the two tables, configure the columns, load the data from a SQL query, then add the relationship.
ds.Tables.Add(dtCustomers)
ds.Tables.Add(dtOrders)
Dim relAccountID As New DataRelation("ConstEnum", ds.Tables(0).Columns("ACCOUNTID"), ds.Tables(1).Columns("ACCOUNTID"), False)
ds.Relations.Add(relAccountID)
We do have some default sort orders and hidden column and filtering added after the relationship, but I have commented out those blocks, with no change in the behavior described above.
Is there some way to force the ultragrid ONLY to look at the child band's rows under the band that row that was clicked?
The initial load times are probably acceptable, given the numbers, but the additional delay is not.
It also appears to be a one-shot delay, as in, in the case of my 10,000 rows, once that extra 8 minute (post right-click) delay has occurred, I can then right click rows freely with normal response time.
I am hoping that is clear enough to sound familiar to you, but if not I can clarify with additional code or information.
Thank you very much.
Hi Michael,
I'm a little confused about what, exactly, is happening. You seem to be saying initially that the problem is due to filtering, but later on in your post you said you turned off filtering and that had no effect.
Filtering in the grid generally takes place the next time the grid paints on the screen following a change in the filter conditions. 10,000 rows with 50 child rows each should take that long.
I can't see any reason why the grid should be loaded data when you right-click on a row. Right-clicking is a no-op as far as the grid is concerned. So is your code doing something to the grid when you right-click?
I suspect there's probably something else going on here - some inefficiency in your code, perhaps in an event handler of the grid, or in the way your grid is set up. But it's impossible for me to guess without seeing it in action.
I recommend that you take a look at the WinGrid Performance Guide. The guide lists the most common performance issues that come up when working with the grid.
If that doesn't help, then perhaps you could reproduce the problem in a small sample project and post it here and I would be happy to take a look.
Yes, I apologize for my inability to ask clearly on this.
When the grid is loaded, it is loaded with the sql data for the two data table queries.
So in this case, it is 10,000 band 0 rows; with about 36,000 band 1 rows (with 1 - 50 per band 0; collapsed by default.) And Band 1 is linked to an ID in band 0, for that relationship mentioned in original post.
The loading of the grid, as I mentioned seemed "acceptable" (probably improvable,but acceptable.)
When I right click a row, we load a context menu for additional choices. By adding a debug statement, I saw that the filterRow event was running for - whatr appeared to be - every single band 1 row in the entire grid, which made up the 'extended' delay I described.
For debugging purposes, I tried:
ugrd.EventManager.AllEventsEnabled = False
and
ugrd.DisplayLayout.Override.AllowRowFiltering = DefaultableBoolean.False
But neither of those seemed to make a difference with the issue described above.
I also commented out various sorting and other extraneous subroutines, without improvement.
I FULLY expect the issue to be a deficiency in my code. But was hoping the issue might sound familiar.
I will review your performance guide, as well as check additional routines associated with the mouse-up/down events that trigger the context menu, to see if that is where the entire grids child rows are being collected as opposed to the rows for band 1 associated with the band 0 that was clicked.
Thank you
UPDATE (since I at least narrowed down the question to the actual problem)
The mouse routine showed the code that is causing the problem, below.
In the mouseup event, after I get the current row/band info; i have a separate routine which needs to get the IDs from all the child rows of the child band under the clicked parent band. My enumerator apparently gets ALL the child band rows as described in the problem. I am not yet certain, how to update the code to only include the subset desired, but I am certain this is the offending code anyway.
The bolded area below needs to be able to return that subset of rows instead of all rows.
Try
_selectedArrayIndex = -1
If ugrd.Rows.Count > 0 Then
Dim aUIElement As UIElement = ugrd.DisplayLayout.UIElement.ElementFromPoint(New Point(e.X, e.Y))
If aUIElement IsNot Nothing Then
If aUIElement.SelectableItem IsNot Nothing Then
If aUIElement.SelectableItem.IsSelectable And aUIElement.SelectableItem.IsSelected Then
Dim aRow As UltraGridRow = DirectCast(aUIElement.GetContext(GetType(UltraGridRow)), Infragistics.Win.UltraWinGrid.UltraGridRow)
If aRow IsNot Nothing Then
If aRow.Cells IsNot Nothing Then
If Not aRow Is Nothing Then
aBand = ugrd.DisplayLayout.Bands(aRow.Band.Index)
End If
If Not aBand Is Nothing And aBand.Index = c_bandCustomers Then
_accountID = DirectCast(aRow.Cells(c_selfPayGridAccountID).Value, Integer)
'Get voucherID array from rows of orders under selected Account band
Dim rowTypes As GridRowType = GridRowType.DataRow
Dim band As UltraGridBand = ugrd.DisplayLayout.Bands(1)
Dim enumerator As IEnumerable = band.GetRowEnumerator(rowTypes)
Dim row As UltraGridRow
Dim selectedOrders As Object = Nothing
_selectedOrders = Nothing 'reset
For Each row In enumerator
If row.ParentRow.Index = aRow.Index And row.VisibleIndex > -1 Then
If (selectedOrders Is Nothing) Then
ReDim selectedOrders(0)
selectedOrders(0) = row.Cells(1).Value
Else
ReDim Preserve selectedOrders(UBound(selectedOrders, 1) + 1)
selectedOrders(UBound(selectedOrders, 1)) = row.Cells(1).Value
Next
_selectedOrders = selectedOrders
Outstanding. I appreciate it. I was vastly overcomplicating what i was trying to do.
So you just want all the child rows under aRow? That's easy:
For Each row as UltraGridRow = aRow.ChildBands(0).Rows
The "0" above is the index of the child band. If you only have one child band, then this is fine, but if you have more than one, it's probably better to use the key of the child band:
For Each row as UltraGridRow = aRow.ChildBands(band.Key).Rows