If I select all rows in the ultragrid in question why are the RowUIElements null.
The code I used is shown below.
Thanks,
Bob
if (browseGrid.Selected.Rows.Count > 0)
{
UltraGridRow
r = browseGrid.Selected.Rows[0];
RowUIElement rowElement = (RowUIElement)r.GetUIElement();
if (rowElement == null)
//?? Why is rowElement = null
return;
I don't know what the requirements of your application are - but if you want the user to be able to interact with the grid and at the same time you are updating the grid 1000 times a second, I don't see how that could possibly work. Obviously, the user would not be able to update a field in the grid, right? Because they could be in the process of editing a cell while it gets updated in code. Or are you only updating non editable fields? I guess in that case, it would be okay.
Using a separate thread to update a bound control is incredibly tricky if not downright impossible to do safely. I can't see anything overtly wrong with the sample you posted here, but your real application is presumably much more complex.
Is the background worker thread in your real application accessing the grid data source or the grid at all? If so, then you are opening your application up to crashing and when it does, it will be nearly impossible to track down. There's a long, detailed discussion of this here:
Work with a dataset bound to a grid on a separate thread - Infragistics Community
Anyway, regarding the sample you have here, when I run the sample, I click on the first row in the grid. This work fine.
Then I scroll down and click on the last row. This initially works just fine. Nothing happens immediately. I get no error and everything looks correct. But then the background thread kicks in and the grid immediately jumps to the top and then your code tries to access the UIElement for a row that is no longer in view.
I never see it raise the exception until after the grid scrolls to the top. I did, as I mentioned, have to change the code a tiny bit to get the sample to function at all. Did you make the same change I made? perhaps something in my assumption about that change is wrong, but I don't think so. Accessing the Cells collection of a GroupByRow should be avoided.
The discrepancy could also be accounted for by the threading. This could just be different timing between your machine and mine caused by the use of the background worker thread. That doesn't seem very likely, but it's something to consider.
Additionally, sorting the grid without locking the active row will always cause the grid to scroll back to the top when resorting. Clearly, this is not a desireable behavior. What if a user were at the bottom of the screen when a particular cell value changes cause the grid to resort? WOuld I want the control to scroll back to the top?
What if this happended 1000x/sec? The grid would be useless
Trust me, using backgroundworker is the only way to accomplish what I'm trying to do here. The backgroundworker is actually processing information in the background in my app. If this wre not done on a background thread the UI would become irresponsive.
I'm using your grid in a real time environment, it's updating probably 1000+ times/second and I need to capture the results of those changes, perform calculations, and set values in the grid based on these calculations. Clearly a timer w/ a begin/end invoke call will not work in this scenario.
The reason that the grid needs to be resorted is b/c your grid does not refresh the group by rows/child rows when the values in the grid change. I need to keep a particular row active before/after sorting but only in the case where the user has not scrolled that row out of view. Checking the UI element should allow me to determine whether or not the row is in view.
I'm not sure what behavior you are seeing, but selecting the last row and keeping it in view in this test app clearly returns a null UI Element reference. You will see the row on the screen, but it will not return a UI element. Simple as that.
Hi,
I ran your sample, but I am getting an assert which prevents me from following the steps you say I need to take. The reason for this is that you are attempting to access the Cells collection on a GroupByRow. I'm not sure why you are doing this. Your code is checking for IsGroupByRow and also checking for row.Cells != null, but this is redundant and even if if was not, you could simply check IsGroupByRow first. So I changed this line of code like so:
//if (ugr.Cells != null && !ugr.IsGroupByRow) if (!ugr.IsGroupByRow)
So now I can run your sample, but I'm having a really hard time following what your code here is doing. You didn't mention anywhere here that you are using a BackgroundWorker thread to sort and update the active row in the grid.
This seems like a very dangerous and unnecessary thing to do. Using another thread to access a UI control is extremely tricky. It seems, at first glance, that you are doing everything right here. You are properly using BeginInvoke to handle everything on the UI thread. But since that is the case, using a thread is actually rather pointless and just adds complexity to your application and gains you nothing. Using a Timer would give you essentially the same results and without the risk of causing a race condition or other threading problem which will be nearly impossible to track down.
To make things worse, you are changing the sorting in the grid, which is also an asynchronous operation, so this further complicates the issue.
Anyway, after I modified that one line of code, I ran your sample and click on the first DataRow in the grid and everything is fine.
Then I scrolled the grid down to the bottom and clicked on the last row. Everything is fine when I do this, at first. But if I simply wait for the Sleep command to finish and the BackgroundWorker thread to start up again, I can see the grid scroll back to the top and then I get a MessageBox that the UIElement was not found. This is all perfectly correct. Sorting the grid scrolls it back up to the top, which scrolls the row out of view, so it no longer has a UIElement.
I'm really not sure what your code here is trying to accomplish, so it's hard to say what behavior you are expecting here. It looks like you are just trying to make sure that the grid is always sorted, but I think you are taking a pretty convoluted and difficult route to achieve that end. You'd be better off simply tracking for whenever a cell value changes or a row is added to the grid and sorting at that point.
In fact, if you comment out line 96 in Form1.cs, the odd behavior seems to disappear.
ultraGrid1.DisplayLayout.Bands[0].SortedColumns.RefreshSort(true);
But that doesn't really help b/c I definitely need a way of forcing the GroupByRows to refresh frequently....