GetNoticed IT#9: User control with data grid and observable collection

Good morning!
It’s been 10 days since my last post so the time is high! Today I’m going to write how to bind an observable collection of custom objects to a data grid in a WPF user control. Some time ago I wrote a post about basic use of user controls (see here) so this post you are reading right now can be considered as extension of the first one.

Objects in collection
Let’s start with preparing a class which objects will be stored in our collection. I won’t look for anything bright, I will just use something for my project: the class will store information about rectangles: height, width, margin and if a rectangle can be rotated. Additionally the class will have a property that returns area of a rectangle.

That’s the basic implementation of our ListedItem class. Now, to use it with observable collection in a way that it is bound to datagrid in UI and all values are automatically refreshed it is necessary to implement INotifyPropertyChanged. At the same time it would be wise to tweak our class a little bit: properties Height and Width cannot be smaller than 1. Also, when implementing INotifyPropertyChanged it is necessary to notify about Area property changed when any of Height or Width changes.

The last step would be to add a parameterless constructor that assigns all properties with default values.

View model
Our observable collection will be stored in our view model.

In the constructor of MainViewModel class we initialize the collection and add first item. And that’s for the purpose of this post is sufficient.

User control
Out user control will consist only of data grid inside a group box therefore the XAML is very simple.

What’s important in the code above are two things marked above: 1) assigning name to the user control (“this”), 2) defining data grid and its binding to dependency property Source.
Now, let’s move on to the code-behind the user control where we define dependency property.

We need to set the property of type ObservableCollection<ListedItem>, owner type ItemsList (as the name of our user control class) and name Source.

Now the last thing: combining all together in view. First of all we need to add namespace that contains our user control to namespaces used by the UI, create an instance of view model that is going to be used be the UI and set it as data context of top level grid.

To add our user control to the UI and bind observable collection for view model:

In this case binding mode is set as TwoWay because I want changes made by user in data grid to be reflected in collection in view model. But you have complete freedom here, that depends only on your needs.

So, basically that’s it. Before I finish few notes about customising the data grid.

The implementation above will generate columns in data grid according to properties exposed by elements in collection. But that is not the only way. you can set up your own names, for instance when you’re building multi-language app. To do that you need first set AutoGenerateColumns property of your data grid to false, and second define the columns manually. In our case that would be:

Note, that you need to be careful to use correct column type and to set binding correctly. In our case Area property is generated automatically therefore user must not be able to put anything in that column. To achieve that I had to set binding mode for this column to OneWay.

User edits
Depending on particular needs you may want to disable editing your data grid. There are certain properties that allows you to customise access to your data grid. To disable any edits you must set IsReadOnly to true, to make more precise customisation you can use set of CanUser properties which are pretty self-explanatory so there’s no point in describing them here.

Thanks for today, I hope that it’s gonna be somehow useful for you.
Regards, Michal