Hi there,
I’m facing a problem when I want to use the XamDataGrid and bind to an object, instead of a primitive value.
In my object I want to store the actual Value and some UI information like FontWeight, Forground, Background or IsEditable and bind them to their opponents.
Right now I’m using a different approach, a global CellValuePresenter and extend this in my CodeBehind, because I need to add dynamically columns to my grid. So I create my own UnboundField and add the PropertyPath to new PropertyPath("Items[" + key + "].Value"), also add my extendet CellValuePresenter, LabelPresenter and an EditorStyle.
In my extended CellValuePresenter Style I do a BasedOn call and set the Setter-Bindings, like
new Binding("DataItem.Items[" + key + "].Background");
new Binding("DataItem.Items[" + key + "].FontWeight");
new Binding("DataItem.Items[" + key + "].Foreground");
But by using this approach I’m facing performance problems and I already read your Blogs about it. When I disable my UI Property, I can increase the performance to an acceptable level (By about 600 rows and 60 columns). I use Recycle for both GenerationMode and activated CelVirtualization and all the small and big tweaks I could find.
And here comes my first question, now I have several CellValuePresenters, because I need per Column (key) a different but makes this the Grid slower? Because now it can’t reuse one single CellValuePresenter and creates and save multiple.
Because of this thought I tried to use an object and bind it directly to my UnbondField, without PropertyPath. And define my UI Property in my base CellValuePresenter and embedded it in my Grid Ressources.
unboundField.Binding = new Binding("Items[" + key + "]");
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Value.Background, UpdateSourceTrigger=PropertyChanged}" />
And see, the Grid gained a decent performance boost.
But now I’m facing another problem. First the Grid shows my object-Type, what it in general fine, because I declared nowhere my “DisplayMemberPath” alike Property. And for this reason, when I edit the displayed underline XamTextEditor-Value, I kill my CellValuePresenter data object. Because the Editors shows the Property Content or Value of the CellValuePresenter as I guess.
I tried to extend the EditorStyle that it will use his ancestor Item and display the objects Value-Property but I couldn’t find the correct way. It shows the value on Start correct but if I change it, it kill the object again, in the CellValuePresenter.
binding = new Binding("Value.Value");
binding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, new CellValuePresenter().GetType(), 1);
style.Setters.Add(new Setter(XamTextEditor.TextProperty, binding));
// or
style.Setters.Add(new Setter(XamTextEditor.ValueProperty, binding));
So here are my big questions.
First, is my thought of the different CellValuePresenter and the performance lost correct?
Second, what would be the most performances way of dealing with this kind of situation?
Third, is it even possible to bind correct to an object or did I miss some step?
Best regards
Andreas
Hello Andreas,
Thank you for your post. I have been looking into it and since I am not completely sure how your data is organized and how exactly you extend the Infragistics classes (e.g. UnboundField, CellValuePresenter), I am not able to investigate this further for you, so could you please send an isolated sample project, whit dummy data, with the same structure whit your original one and the extensions you made, so we can think of a possible solution for you. Also could you give us more details about the result you want to achieve?
Looking forward for your reply.
Hello Stefan,
Thanks for your reply! I tried to reduce my DataGrid to the relevant components and attached this to the post.
The relevant classes are BaseWorkspace.xaml, the CodeBehind of this class and for Data generation the Workspace-Model. The workspace-model contains a collection (ParametertableItem), that represents my rows aka datarecords. In this TableItem I store another collection of Cell, which will be my records and defines the amount of columns I want to be displayed.
In this example the BaseWorkspace.UpdateGrid() methods get called by the constructor and generates at first my fixed meta-columns (createMetaCell()). After that it creates my UnboundsFields for my Parameter Values, their displayed values can and will by change in their lifecycle.
In my first approach I bind to my TableItem with the specific key/column and to my Value.
var propertyPath = new PropertyPath("Items[" + key + "].Value");
After that I bind some extended UI-Information
unboundField.Settings.CellValuePresenterStyle = createDataStyle(key);
unboundField.Settings.LabelPresenterStyle = createLabelStyle(project);
unboundField.Settings.EditorStyle = createEditorStyle(key);
private Style createDataStyle(string key)
{
…
binding.Mode = BindingMode.OneWay;
binding = new Binding("DataItem.Items[" + key + "].Background");
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
style.Setters.Add(new Setter(CellValuePresenter.BackgroundProperty, binding));
binding = new Binding("DataItem.Items[" + key + "].FontWeight");
style.Setters.Add(new Setter(CellValuePresenter.FontWeightProperty, binding));
binding = new Binding("DataItem.Items[" + key + "].Foreground");
style.Setters.Add(new Setter(CellValuePresenter.ForegroundProperty, binding));
binding = new Binding("DataItem.Items[" + key + "]");
style.Setters.Add(new Setter(TagProperty, binding));
return style;
}
Now I want to bind to my ParameterValue-Object direct, instead of the ParameterValue.Value. With this approach I want reduce my dynamically binding in my createDataStyle(key)-method.
After that I want bind my UI-Properties through a RelativeSource binding. But right now I don’t really know how to bind the value itself, Background or FontWeight is no problem.
<Style x:Key="ParameterCellValuePresenter" BasedOn="{x:Static igThemes:DataPresenterIGTheme.CellValuePresenter}" TargetType="igDP:CellValuePresenter">
<Setter Property="FontWeight" Value="{Binding RelativeSource={RelativeSource Self}, Path=Value.FontWeight, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Self}, Path=Value.Foreground, UpdateSourceTrigger=PropertyChanged}" />
</..>
I added some case when the Background is changed.
Value < -10000 => red
Value > 1000 && para.Value < 100000 => green
The Fontweight change, when the value is changed
BR
I have been looking into your sample and I comment and uncomment the code from the UpdateGrid method, but I didn't notice any performance difference. Also I can see all the values displayed, so I am not completely sure what issue you have with the bindings for the UnboundFields.
Hi Stefan,
I added two edited projects to the attached file. The first own (slim) use no defined styles and runs in my opinion pretty smooth. The second example (object binding) binds an object to the UnboundField and in this case I don’t know how to get the Value to be displayed.
My first goal at this point is to improve the scrolling performance.
I have been looking into your sample (object binding) and I can suggest you set the UnboundField's BindingPath Property instead of its Binding. It should look like this:
unboundField.BindingPath = new PropertyPath("Items[" + key + "].Value");
This code should be edited in the UpdateGrid method from the BaseWorkspace.xaml.cs file. Please let me know if this helps you or you have further questions on this matter.