Hi there
I have a problem with Ultragrid whereby it's losing the column layouts I set at design-time when the app is run. I'm getting this in several places in my app and it seems to occur at random, the grids are working fine, then they just lose their settings, even when that part of the app hasn't been worked on.
I've had a good read through what's been posted previously on this, and I understand that this is probably due to the runtime datasource not matching what was set at design-time. I can't really understand how this would be the case as the full column list displayed at design-time matches up the columns shown at runtime.
My questions are;
E.g.
Parent object is a CustomerClass, and CustomerClass has a child collection of CustomerClass.OrdersList.
The form is bound to the CustomerBindingSource, which has a datasource of CustomerClass
the grid on the form is bound to a OrdersBindingSource, which has a datasource of CustomerClass and a datamember of "OrdersList".
Any help in getting to the bottom of this would be much appreciated, it is driving me nuts!
Hi Mike
That's great info, many thanks.
Since writing the last post I have discovered something decidedly odd: When I start VS I get the problem with the grid not retaining it's layout at runtime, and now VS cheerfully announces that it cant find the collection name in the binding source - this would explain why it is resetting the grid.
If I stick a breakpoint in the autogenerated code, then run the code, hit the breakpoint, then carry on I get no more problems, it all works as expected and the layout is retained.
Sounds like a timing issue to me? My GUI is in a different assembly to the classes the GUI is bound to, so I'm wondering if there is an issue there somewhere, not necessarily an IG issue, maybe just a problem with the assemblies registering in time.
I'm also now getting a memory leak somewhere, devenv.exe hit 600mb before all the IG controls announced they couldn't paint.
Something very weird is afoot here..! The problem is with the both the IG and .Net Controls code being blackboxes, and neither reporting exceptions, I'm absolutely blind on what can be happening.
tom_redox said:My thinking was that it would be easier to find the issue if the grid threw a message along the lines of "Key "CustomerID was not found, grid layout reset" - this would then give me a start on working out where the problem lay.
Ah, yes, I see your point. I was thinking in terms of trying to fix it in an event. But yes, if you could trap when it happens, it might help us narrow it down and avoid / fix the issue.
Unfortunately, there is no such notification.
tom_redox said:That's interesting to know. Our grids are based on custom collection classes, how do the keys for the bands work for these?
That depends entirely on the BindingManager and the classes themselves. Any time I am unsure what the key of the bands will be, what I do is simply bind a new grid to the data source at run-time, loop through the Bands collection, and display the keys.
tom_redox said:A couple of other question on this, do keys need to be unique for columns across bands. E.g. if the Customer (Band 0) has a Date Entered field and so does the child OrdersList collection (Band 1), would that cause an issue?
No, you can have a column with the same key in different bands and that is no problem.
tom_redox said:Also, we use the System.ComponentModel DisplayName attribute on our classes to set a friendly name for each property of the class. This is then used by the grid to set the column headings. Do these values play any role when assessing whether the runtime and designtime schemas match and are duplicates in these column headings an issue?
No, this only affects the display, it is not used in anything relating to structure.
tom_redox said: Ouch.. so effectively that means setting the key, column header text plus any formatting, plus any custom editors and the displaystyle etc for every column manually in code? I guess I could cut and paste this from the auto-generated designer code after the first setup of the grid?
Ouch.. so effectively that means setting the key, column header text plus any formatting, plus any custom editors and the displaystyle etc for every column manually in code?
I guess I could cut and paste this from the auto-generated designer code after the first setup of the grid?
You can't set the Key. The key comes from the data source. And the DisplayName field will automatically get picked up from the DataSource as well and applied to the column header.
Customer editors, display styles, formatting, column size and positions, etc. are the things you would need to set up. But you only need to write the code once and you will never lose your layout again - barring a hard drive crash or something like that. :)
Thanks for your detailed response. I should have made it clearer in my initial message that the grid is bound to a collection object (specifically a csla collection implementing all the MS binding interfaces).
Mike Saltzman"] There's no way to trap for this. But if there were, I'm not sure I see how that would help.
There's no way to trap for this. But if there were, I'm not sure I see how that would help.
My thinking was that it would be easier to find the issue if the grid threw a message along the lines of "Key "CustomerID was not found, grid layout reset" - this would then give me a start on working out where the problem lay.
Mike Saltzman"] I don't think the grid looks at the data types of the field. It looks at the columns (number of columns and the keys of the columns) and also the bands (number and keys). The most common problem I encounter is that people get the keys of the bands wrong. The key isn't always what you think it is. For example, when using a DataSet, the key of the child band is the name of the relationship, not the child table.
I don't think the grid looks at the data types of the field. It looks at the columns (number of columns and the keys of the columns) and also the bands (number and keys). The most common problem I encounter is that people get the keys of the bands wrong. The key isn't always what you think it is. For example, when using a DataSet, the key of the child band is the name of the relationship, not the child table.
That's interesting to know. Our grids are based on custom collection classes, how do the keys for the bands work for these?
A couple of other question on this, do keys need to be unique for columns across bands. E.g. if the Customer (Band 0) has a Date Entered field and so does the child OrdersList collection (Band 1), would that cause an issue?
Also, we use the System.ComponentModel DisplayName attribute on our classes to set a friendly name for each property of the class. This is then used by the grid to set the column headings. Do these values play any role when assessing whether the runtime and designtime schemas match and are duplicates in these column headings an issue?
Mike Saltzman"] Personally, I have found that the BindingManager in DotNet is a bit quirky and sometimes sends reset notifications at unexpected times. So I prefer to set up my layouts at run-time in the InitializeLayout event of the grid. That way, there is never any chance of losing it.
Personally, I have found that the BindingManager in DotNet is a bit quirky and sometimes sends reset notifications at unexpected times. So I prefer to set up my layouts at run-time in the InitializeLayout event of the grid. That way, there is never any chance of losing it.
tom_redox said:How do I check that this is the case - i.e. what's the bet way to debug this. I take it the grid doesn't throw an exception to say the datasource didn't match up with the layout?
tom_redox said:What are the possible causes of this - how does the grid decide whether the datasource has changed? Is it just looking for matching field names and datatypes or is there more to it than that?
tom_redox said:What's the best practice for setting up the bindingsources for grids? Currently I have a bindingsource for the form which has a child list property that is displayed in the grid. The grid is bound to a second bindingsouce which has its datasource set the form's datasource and the datamember set to the child list property. At runtime all I do is then set the parent bindingsource's datasource to an instance of the class. Does that sound right?
I'm not sure I follow you there. If you want to set up the layout of the grid at design-time, then there are really two ways to do it:
Another way to do it is to set up the layout at design-time and save it using the layout wizard. You can store the layout to a file or into the grid's Layouts collection, then load it at run-time.