Saturday, April 10, 2010

RowDetailTemplate of DataGrid control

When I started my learning of silver light 3.0, and see the control offered by the tool, one of the controls which I like most in every programming language is the data grid control. The feature offered by the new data grid control are very good especially the RowDetail. Which is the best feature from my point of view as you can show additional detail of the record in the Row Detail, it is mostly used when you have situation where you need to show parent and child records. When I used data grid control in silver light application the question in my mind was how to display data grid in the RowDetail, and I have search on it on Google but didn’t find good solution at that time. But now once again I have tried again and now this time I have find the solution of displaying data grid in the RowDetail. Below is the main data grid when user didn't click on any of the row.
And here is the row detail of the grid when user click on any of the data grid row, to see the more detail about the record.

Let us start with our example code I have one data grid control and in that data grid control I have placed another data grid control which is placed in the RowDetail template. I have two classes one for with the name of Persons and second one with the name of PersonDetail. In the Person class I have following properties user id, first name, last name, email address and the contact number. In PersonDetail class I have Parent ID, Programming language and the skills level properties. I have just used the programming languages such as WPF, WCF , silver light, php , asp.net etc. for just display purpose and each record in the Persons class has two child records so that when user click on any of the row , it shows its relevant record, I have also displayed the Parent ID in the child table so that you can see the relation ship id as well. Below is my xaml code, here you can see that I have placed grid control in the RowDetailTemplate of the main data grid, and I have also set the columns properties such as header , binding etc of the child data grid control.
<data:DataGrid Margin="5,5,5,0" x:Name="dgrdDataGrid" GridLinesVisibility="Horizontal" AutoGenerateColumns="False" VerticalAlignment="Top" RowDetailsVisibilityChanged="dgrdDataGrid_RowDetailsVisibilityChanged" IsReadOnly="True">
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="User ID" Width="80" Binding="{Binding UserID}" CanUserReorder="False"/>
<data:DataGridTextColumn Header="First Name" Width="150" Binding="{Binding FirstName}" CanUserReorder="False" />
<data:DataGridTextColumn Header="Last Name" Width="150" Binding="{Binding LastName}" CanUserReorder="False"/>
<data:DataGridTextColumn Header="Email Address" Width="150" Binding="{Binding EmailID}" CanUserReorder="False"/>
<data:DataGridTextColumn Header="Contact" Width="100" Binding="{Binding ContactNumber}" CanUserReorder="False"/>
</data:DataGrid.Columns>
<data:DataGrid.RowDetailsTemplate>
<DataTemplate>
<data:DataGrid x:Name="dgrdRowDetail" Width="400" AutoGenerateColumns="False" HorizontalAlignment="Center" IsReadOnly="True">
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="Parent ID" Binding="{Binding ParentID}"/>
<data:DataGridTextColumn Header="Programming Language" Binding="{Binding ProgrammingLanguages}"/>
<data:DataGridTextColumn Header="Skill Level" Binding="{Binding SkillLevel}"/>
</data:DataGrid.Columns>
</data:DataGrid>
</DataTemplate>
</data:DataGrid.RowDetailsTemplate>
</data:DataGrid>
Next the important thing is I have registered the RowDetailsVisibilityChanged event of the main data grid control , which is fired when RowDetailVisibilityMode property value changes, when user click on any of the row then it will fires , and in this event I will filter the records depending on the Persons ID and then assign it to the RowDetail data grid control.
Here is the complete code of the RowDetailVisibilityChanged event handler, here you can see that I have place if condition to check the dataContext of the row for null and then use form filter of the data to get only record which are matched with the current user id.

try
{
if (e.Row.DataContext != null)
{
var objCurrentRecordDetail = from tblPersonDetail in objPersonDetail
where tblPersonDetail.ParentID == ((Persons)e.Row.DataContext).UserID
select tblPersonDetail;

((DataGrid)e.DetailsElement).ItemsSource = objCurrentRecordDetail;
}
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message, "Error", MessageBoxButton.OK);
}
Next is the statement which is used to assigned the item source of the data grid which is placed in the RowDetail. Here I have used the EventArgs parameter of the RowDetailVisibilityChanged event handler and use the property DetailElement, as I have only one control in the RowDetail , so here I can find the main data grid control in the DetailElement property. Suppose if you have Grid layout in the RowDetail and you have your own display of the RowDetail then you can use e.DetailsElement.FindName("dgrdRowDetail") to find the data grid in my case and any of the control which you want to search in the grid control. In this case e.DetailElement Property will return you the grid control. Then you have to search for your control in that grid layout.You can download the source code from here
All and any comments / bugs / suggestions are welcomed!

6 comments:

Unknown said...

Do you know that your sample code return below error -

Unable to cast object of type 'System.Windows.Controls.Grid" to type 'System.Windows.Controls.DataGrid'?

Could you re-publish the code?

Asim Sajjad said...

Ada: I have tested and then uploaded my sample example, will check it and then you what is wrong with it. But it was running fine.

Dana Lizuca said...

I am getting the same error ... "Unable to cast object of type 'System.Windows.Controls.Grid'
to type
'System.Windows.Controls.DataGrid'."

:0)

Could It be because I am using VS 2010?

Asim Sajjad said...

Sorry that was my fault, I have check it again and now I have remove error form the code you can download it from here
http://asimsajjad.googlecode.com/files/Grid Inside Grid (Removed Error).rar

thanks for your participation, thanks alot again

Asim Sajjad said...

Sorry that was my fault, I have check it again and now I have remove error form the code you can download it from here
http://asimsajjad.googlecode.com/files/Grid Inside Grid (Removed Error).rar

thanks for your participation, thanks alot again

Unknown said...

It's working now. Thanks!