I've set the dataschema manually in my ultraGrid1 (version: 12.1.20121.2135).
I have a List<Person> and every Person class has a List<Order>.
The datasource property of the grid is simply set at runtime, like:
List<Person> People = DummyRepository.GetPeople();
ultraGrid1.Datasource = People;
At first none of the people have an Order in their collection. At runtime the user can add an order. When the user does this I set the datasource again with People. But unfortunatly it doesn't show the added Order. I tried after setting the datasource property:
ultraGrid1.Rows.Refresh(Infragistics.Win.UltraWinGrid.RefreshRow.ReloadData)
ultraGrid1.Rows.Refresh(Infragistics.Win.UltraWinGrid.RefreshRow.RefreshDisplay)
And even:
ultraGrid1.Databind()
Nothing helps.
The only thing that seems to help is setting the datasource to null first and then setting the datasource to the collection. But then I have another problem, which I'm not sure I should get in to right now. You see I also have custom Row Layouts which I havent mentioned yet. But if I set the datasource to null the grid loses the custom row layout I designed in the designer at runtime.
I can set the datasource to null and keep displaylayouts by first saving and then loading the displaylayout, but... That shouldn't be the solution. Feels pretty forced to me. Besides I'll lose other properties like spacing between rows and such appearances.
So... How can I solve this?
Hi,
List<T> is not a good data source to use for bound controls. This interface will only provide basic support for binding, and it doesn't have all the property notificaitons for data binding. I recommend changing to BindngList<T>, instead. I'm not sure if that will solve this particular problem, but it will certainly save you some headaches down the road.
If it doesn't solve the issue, the my guess is that grid cannot build the proper structure from your data source. Implementing your own data objects like this can be tricky and the grid will build the bands up front as soon as it's bound. So if the data source originally has no Order data, then the BindingManager might be unable to create the child band structure and that's why it's not working.
Make sure that, even when there are no Order rows, you Person object always returns an empty list (not null).
If that still doesn't help, see if you can post a small sample project here so I can check it out and I will figure out why it's not working in your case and let you know how to fix it.
Hey Mike,
I know about BindingLists and have my reasons not to use them. So let me deal with the headaches. :-)
In my real project, the collection is already an empty list (I believe I already got this tip some time ago from Infragistics but new requirements made the problem return).
So I have attached a small project to illustrate my problem. It's called PersonOrderRefreshing.
1) Run it.
2) Press "add order" and you'll see the grid refresh correctly.
3) Now in method RefreshGrid() of Form1 put the call to RefreshGridAll in comment and decomment RefreshGridActive.
4) Run the project.
5) Press "add order" and you won't see the grid refresh properly. Why?
6) Decomment all code in RefreshGrid
7) Run it.
8) Add orders and try to switch between active/all People. Doesn't work either. Why?
Thank you in advance for looking into my problem.
Hello Georgi,
Thank you for making an improved sample for me and a little video. I appreciate it very much.
It works in my real project aswell. So, nice find. But this solution gives me other problems (because ofcourse in my real project the objects are more complex plus I like to code with obj.equals(obj) which needs to be the actual instance of the object as you know).
In other words, if I'm going to implement this solution I'll have to rewrite a lot.
So my question is: Why does it work like this?
If you create entirely new objects the grid seems to be tricked into reloading the data. But if I use your Refresh method with ReloadData it doesn't. Why?
oh p.s: I did alter the LINQ query a bit, like so:
var activePeople = (from p in DummyRespository.People where p.IsActive select new Person { Name = p.Name, IsActive = p.IsActive, Orders = p.Orders.ToList() }).ToList();
Because I like to work with strongly typed instances. I also applied this in my real project.
p.p.s.: Also found out that first setting datasource equal to an empty list and then to a filled list has the desired effect???
I'd have to delve into this more deeply to find the exact cause, but I think it's clear that the grid is caching it's rows and since you are creating a new List<T> that contains the same instances as the objects in the original list, the grid is making the assumption that these objects are the same.
The grid probably shouldn't be making that assumption when it's DataSource is a completely new object and the Refresh(ReloadData) should probably be blowing away the old cache, but I'm not 100% sure if that's the correct behavior or why the grid behaves as it does now. There might be a reason for it, and changing this behavior could cause breakage in existing applications, so we need to be careful here with any changes we make on our end.
Creating new instances of the objects doesn't seem like an ideal solution, either, though.
I'm going to ask Infragistics Developer Support to write this up for developer review so we can investigate further and possibly get this fixed in a future service release.
Mike,
You are spot on with the caching I think. That was my assumption too.
As a user of the gird however I really thought Refresh(ReloadData) forces the grid to get rid of the cache and reload the collection. But like you said, you don't want to break existing applications. So got to be carefull.
I have a solution for my real world application now. I set an empty collection as datasource and then the filled collection. This seems to reset the cache and maintain the dataschema and custom row layouts. So I'm happy for now.
Good luck trying to find the solution to this. Keep me updated please.
DannyvdK said:I have a solution for my real world application now. I set an empty collection as datasource and then the filled collection. This seems to reset the cache and maintain the dataschema and custom row layouts. So I'm happy for now.
That seems like a reasonable workaround.
Hi Danny,
I looked into this in detail, and it turns out to be very simple. The problem is that you are calling:
this.ultraGrid1.Rows.Refresh(Infragistics.Win.UltraWinGrid.RefreshRow.ReloadData);
instead of:
this.ultraGrid1.Rows.Refresh(Infragistics.Win.UltraWinGrid.RefreshRow.ReloadData, true);
The second parameter is for 'recursive'. By default, the operation is not recursive, so it doesn't refresh the child rows. So you just have to pass in true to refresh the child rows and it works fine.
Oh gosh! That is very simple. Well it must've been. Didn't understand why you guys would miss that. Turns out I've overlooked that parameter.
Thank you for looking into it in detail. I've marked your post as the answer.