Hi all,I am currently facing a strange problem with the WinGrid.It is a standard WinGrid, bound to an object datasource (List<item>).I added an UnboundColumn to display a "light" icon that indicates its status (red, green).On InitializeRow the calculation is done and a predefined (for reuse) Appearance is assigned to the cell (unbound column).Now imagine the following rows (Id, IndicatorImage):1 green2 green3 red4 red
now if I remove the data entry from the datasource that contains Id = 2 I assumed to have the following rows:1 green3 red4 red
Unfortunately I get this:1 green3 green4 red
It seems that the indicator image stays the same for the rows (the bottom one is removed though)
Any hint is kindly appreciated,best regardsAndy
Hi Andy,
Can you post your InitializeRow code so I can see what it's doing? It seems to me that, since the color on the existing row is changed, the InitializeRow must be firing for that row and the InitializeRow code must therefore be applying the wrong Appearance to the row.
Also, what version of the grid are you using? It's also possible that this is a bug in a very old version of the grid where it's re-using the UIElements incorrectly. But that bug was fixed many years ago.
Hi Mike,
good hearing from you, I hope you are doing fine.
Here is the InitializeRow code:
void grdBalance_InitializeRow(object sender, InitializeRowEventArgs e) { if (e.Row.GetType() == typeof(UltraGridRow)) { // checking flag-state ParsedBalanceStorageListEntry entry = e.Row.ListObject as ParsedBalanceStorageListEntry; int count = GetCountFromItem(entry); if (count == 0) { e.Row.Cells[TrafficLightColumnKey].Appearance = RedMarkerAppearance; return; } if (count == 1) { e.Row.Cells[TrafficLightColumnKey].Appearance = GreenMarkerAppearance; return; } e.Row.Cells[TrafficLightColumnKey].Appearance = YellowMarkerAppearance; return; } }
...and the stuff related to the appearances I use:
private Appearance _greenMarkerAppearance; private Appearance GreenMarkerAppearance { get { if (_greenMarkerAppearance == null) { _greenMarkerAppearance = GetDefaultTrafficLightAppearance("GreenMarkerAppearance"); _greenMarkerAppearance.Image = GlobalResources.Images.Misc.Flags.NonCountryFlags.NonCountryFlagsImageProvider.FlagGreen.ResizeTo(new Size(16, 16)); } return _greenMarkerAppearance; } } private Appearance _redMarkerAppearance; private Appearance RedMarkerAppearance { get { if (_redMarkerAppearance == null) { _redMarkerAppearance = GetDefaultTrafficLightAppearance("RedMarkerAppearance"); _redMarkerAppearance.Image = GlobalResources.Images.Misc.Flags.NonCountryFlags.NonCountryFlagsImageProvider.FlagRed.ResizeTo(new Size(16, 16)); } return _redMarkerAppearance; } } private static Appearance GetDefaultTrafficLightAppearance(string key) { Appearance appearance = new Appearance(key); appearance.ImageHAlign = HAlign.Center; appearance.ImageVAlign = VAlign.Top; return appearance; }
I use this to meet the guidelines I read about in your UltraGrid Tuning-Tips article for reusing appearances.
We are currently using version 11.2.20112.1010, so I assume that is already a version where the mentioned bug was fixed ;)
Let me know if you need any further information.
Best regards and have a great dayAndy
Hi,
I don't see anything wrong with this code that would cause a problem - assuming that GetCountFromItem is correct - and there's no reason to think it isn't.
My only guess at this point is that maybe the fact that the grid is processing the data source operations asynchronously is causing things to get out of synch. To test that theory, after you remove the row from the data source, try adding this:
grid.Update();
grid.Rows.Refresh(FireInitializeRow);
If that doesn't correct the cell appearance, then I'm not sure what's going on. Could you post a small sample project demonstrating the behavior so we can check it out?
Hi Mike,thanks a lot for your reply, I am going to test what you proposed and let you know how it worked out.Unfortunately I will be able to do this at the earliest of Monday.
I didn't implement the Update/Refresh because I could see the entry disappear from the list upon removal and I didn't even recognize the problem until the testers could get a hand on it..
I just have one concern regarding this, because the routine for GetCountFromItem is quite heavy weighted, but I am pretty sure if this approach works I can implement buffering or anything alike to make this less heavy.
By the way, I do not use threads in this project, so this shouldn't interfere with the grid.
Thanks again Mike and have a great weekendbest regardsAndy
Okay, let me know how it goes.
Yeah, that's pretty much what I thought. There has to be something in GetCountFromItem that is getting the wrong data at that particular point in time.
Hi Mike,I made a sample to see if it is related to the grid, but I wasn't able to reproduce it.Even without updating the grid and refreshing the rows it works fine, it takes a while but it works fine...
If you are interested I can send you the sample.
Anyway, your solution for fixing the problem works fine and I'll stick to it. Adding buffers was easy, so it performs pretty fast now.
Thanks a lot for your help Mike, I really appreciate your great support!
have a great time,cheersAndy
Sure, if it looks like this is a problem with the grid, then please post a sample duplicating the issue and we will be happy to check it out.
I am not quite sure if I get this correctly.
The GetCountFromItem uses a different datasource that the grid.
The grid is actually bound to a List<item> that is disconnected from the database.So removing the item from the List<item> via a call to the Lists "_list.Remove(item)" function just removes the item and does not involve any database operations at this point.
Funny was that the order of the IndicatorImage stays the same if you look at it from the top. So if I removed an item from the middle the IndicatorImages stay the same from the top. It looks like that all rows after the deleted one just move one up and the bottom one is removed completely, leaving the order of indicator images intact...
Like if you just empty the row of the deleted item (only the cells that do not show the image). Then move all lower entries (only cells without image) one up which results in the bottom row only containing the image and empty cells. Then remove the bottom row...
I am going to do a test tomorrow with a simple structure and check if this is happening there too. I will send you the project if it turns out to behave the same, would that be ok? If it doesn't behave like this the problem is in my structure.
cheersAndy
Yes, I see from the code here that you are passing the ListObject into the GetCountFromItem method. It looks to me like the ListObject of the row is correct - it has to be or the grid would not be showing the correct value in the first column. But GetCountFromItem must be accessing data from the data source that hasn't caught up to the delete operation, yet.