Friday, September 10, 2010

Binding DataGrid RowDetailTemplate Using MVVM

In this post I will show you how you can bind the RowDetailTemplate of the data grid using the MVVM pattern. Below are the image of the sample code here you can see the default page in Image 1 and when user click on any of the record then detail of the record is shown in the RowDetailTemplate which also consist of the data grid control which you can see in the Image 2.

Image 1
Here in the Image 2 you can see the RowDetailTemplate of the selected record. Here you can see the user id , programming language and the Expert Level ( Column names which are displayed in the inner data grid control).

Image 2

Let us start with the sample code. I will explain model first , then the view model and at the end the view.

1- Model:
               In the model I have two classes one is the Persons and second is the PersonDetail. The Persons class consist of the user id, first name, last name, email id , contact number and date of birth properties. The Persons class will be used to show records in the main data grid, which you can say the outer grid. The Persons class has only one function which is GetPersonRecord which is used to return the list of Persons records and the function is static so just call the GetPersonRecord function by using the class name.The PersonDetail class consist of three properties which are user id, programming language and the Expert Level. The PersonDetail class will be used to show records in the RowDetailTemplate ( Which consist of one data grid control to show the Person expertise in programming language). The PersonDetail also have one static function which will return list of PersonDetail records.

2- View Model : 
            The view model only consist of one class MainWindowViewModel. This class will be used to bind with the MainWidnow view. The MainWidnowViewModel is inherit from the INotifyPropertyChanged interface.The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed. The ChangedProperty event of  INotifyPropertyChanged is implemented. The view model also consist of three properties one is used to bind the outer data grid control and second is used to bind selected value and third one is used to the bind the inner data grid which is used to bind the RowDetailTemplate data grid control.PersonRecords is the property which is used to bind the outer or main data grid control, as I need to bind the data grid control for just display of records so I will not raise RaisePropertyChanged event for this property as only one time binding is required in this case. PersonRecords property will get/set the list of Persons records and It will be initialized on the constructor of view model class.Second property is SelectedRecord which is used to bind with the outer/ main data grid selectedItem property. As I have to filter the record for the RowDetailTemplate data grid control. When the value of the SelectedRecord property will be changed then I have raised the RaisePropertyChanged event as I will filter the details record based on the current selected record in the outer/main data grid control.Below is my code which is used to filter record in the RaisedPropertyChanged function. As the PersonDetail.getPersonDetail() will return the list of PersonDetail, So by using the LINQ technique I have filter record based on the SelectedRecord user id.

if ("SelectedRecord" == pstrPropertyName) SelectedPersonDetail = PersonDetail.getPersonDetail().Where(param => param.UserID == SelectedRecord.UserID).ToList();

The last and the important property in the view model is the SelectedPersonDetail property, which is used to bind with the RowDetailTemplate property. As the SelectedPersonDetail property will changed every time user click on the row in the outer/main data grid control so RaisePropertyChanged event will be fired every time the value of the SelectedPersonDetail property will changed.

3- View :
         The view is very simple one here the outer/main data grid Item source and SelectedItem properties are set. The imported property which is used to bind the Item source of the RowDetailTemplate data grid is listed below, I have only write the xaml of the Item source of the data grid control.

ItemsSource="{Binding Path=DataContext.SelectedPersonDetail , RelativeSource={RelativeSource AncestorType=Window}, Mode=OneWay}"

In the above xaml code you can see that I have used RelativeSource to bind the Item source of the RowDetailTemplate data grid control. The RelativeSource property is used to specify as a source an object that is positioned relatively to the current object. Once again, this property is used when there is a need to specify a source other than the DataContext of the object.FindAncestor mode allows the retrieval of an ancestor of the current object based on its type. I have specify type to be window as I want to bind the DataContext property SelectedPersonDetail which will be the filtered records of the selected persons records.You can download the source code from here.

All and any comments / bugs / suggestions are welcomed!


syed kalim said...

I really like ur articles.These stuffs always been very useful for me.Well i have seen ur articles on MVVM and they are all very good but can u please post an articles using MVVM and WPF that how it'll work by using DATABASE.
Many thanks in advance.

Asim Sajjad said...

@kalim: thanks for your comments and feedback and it really nice to hear that you get some knowledge from my post, regarding your reqest to have MVVM using database, I think you can do your database operation in Model ,the model will communicate with the database, But I will try in future to create application using database.

Anonymous said...

Do you have a code sample someone could look at?

Asim Sajjad said...

Anonymous: Code sample is given at the end of the post.

Anonymous said...

hi i could not understand the selected property code...can u explain in details what the lambda exp is doin ..please

Anonymous said...

Hi Asim,

Very good article, this is really helpful to me. I am working on similar requirements and this article help me lot. I have small change that my main grid has checkbox column and I want to show the detail grid only when checkbox is clicked. Can you help me out.


Waref said...

Hello Sir,

Plz can you give a new link to download the simple ?

Nilesh said...

Need sample code