Hello,
I'm trying to create a simple real-time application with the grid control.
Currently our data source is an observable collection of objects that implement INotifyPropertyChanged. It consists of a grid of 1000 rows and 20 columns, where every single value in the data source is updated every 500ms. This means that there are 40,000 updates every second to the data source.
xamDataGrid will lazy subscribe to each row as it appears on screen, however it never unsubscribes, meaning that once you have viewed every row, the grid makes 40,000 calls a second to the dataset to get the data rather than the 400 or so of the cells actually on screen.
Is it possible to somehow setup the grid so that it only actively subscribes to the data that is onscreen at that time? Any suggestions appreciated.
ThanksSteve Mortimer
Hi Steve,
Even though we subscribe to records not in view, I don't understand how it is accessing the data for cells not in view, unless you have set the RecordContainerGenerationMode property to 'PreLoad' or 'LazyLoad' since internally we call CellValuePresenter.FromRecordAndCell and only re-get the cell's value if it returns a non-null value. For RecordContainerGenerationMode 'Recycle' (which is the default) or 'Virtualize' that should only apply to records in view plus possibly a small # of buffered records in the 'Virtualize' case.
Hi Joe, thanks for your respose.
Digging a little deeper and moving the code out into a tester application i think we have moved a little closer to my issue.
You are correct that if we allow the grid to autogenerate the columns the the behaviour is as described. The problem is that we have to generate the columns dynamically as the dataset is really an observable collection of sets of objects. We use reflection at runtime to create UnboundFields and bind into the observable collection of objects.
foreach (PropertyInfo pi in t.GetProperties()){
string bindingPath = string.Format("ColumnSets[{0}].{1}", t.Name, name);
column.Name = name;
column.Label = name;
column.BindingMode = BindingMode.OneWay;
column.DataType = pi.PropertyType;
etc.
So im guessing that this issue is either me not understanding WPF binding, not understanding the correct way of using the grid, or something special about UnboundFields.
Our grid is part of a view which takes a model of data which is extensable via plugins, therefore we dont actually know what columns were going to have until runtime. We did try using a dataset at one point however found its speed slower than an observable collection.
Any ideas on a better way of achieving what we want?
Thanks
Steve
Steve,
I am not clear on why letting the grid autogenerate the fields doesn't work in this scenario. The xamdatagrid will do almost exactly what you are doing in your sample code, with the exception of creating Fields instead of UnboundFields.
Why is this not usable in your scenario?
Hi Joe,
I am replying for my collegue. ColumnSets (as in the example given by Steven - see the binding path) is a collection which contains sets of columns only available at runtime. The problem is the Field object can only bind to a property, and in this case we have to give it a path to the property. Is there a way we can achieve this with the Field class?
Thanks,
Stefan
Hi Stefan,
It was my fault, I didn't look ate the code closely (my brain must have gone on sabbatical).
I understand the problem now. We are lazily creating bindings for the UnboundCells internally but don't clear those bindings as records are scrolled out of view. This problem only affects the cells of UnboundFields.
As long as you are using UnboundFields there is not much you can do until we address the issue in our code.
One approach to get around the problem with the current bits is to have your collection implement the ITypedList interface and have the GetItemProperties method return a collection of derived PropertyDescriptors, a class that you write that e.g. takes the real property descriptor and the model type in the constructor, and then delegates its property and method calls to the real property descriptors. If this is not clear let me know.
The advantage to this approach is that from the xamdatagrid's perspective it will get a collection of propertydescriptors that it can create Fields from thus obviating the need for you to create UnboundFields. I know that it is a bit of a hassle but it is the best solution I can think of with the current bits.
I hope this helps.
This approach worked fine if i have a ObservableCollection<MyObject>, but now I am willing to use ColectionView as my source for the gridn and have the SourceCollection be ObservableCollection<MyObject>. So i have my class implementing CollectionView and ITypedList to expose my properties for binding and unfortunately is not working, by debugging it looks like it is ignoring the ITypeList interface as the GetProperties method never gets fired. Am I doing something wrong?
Regards,