Silverlight 4: Master Details with two DataGrid

In cases where you are fetching data from Master/Detail (Parent-child) relationship tables, users demand a functionality where the Silverlight page contains two DataGrids for holding Parent and Child table data respectively. When a row from parent DataGrid is selected, the child DataGrid should display the data from the child table. To achieve this, you can work with minimum code-behind and make effective use of the DataBinding features of Silverlight 4.0. In the small snippet shown below, I have explained the way of achieving this requirement using DataBinding features of Silverlight.

Create a new Silverlight application and add the two classes as below (Note: These classes may be entities from ADO.NET EF using WCF Data Service or WCF Service publishing DataContracts.)

Silverlight Parent Child Grid

Open MainPage.Xaml and write the following XAML code (The best way is use VS2010 and its Drag-Drop features for DataGrid and other controls. The Binding expressions are taking help from the Code-Behind)

<UserControl x:Class="SL4_Parent_Child_Grid.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:data="clr-namespace:SL4_Parent_Child_Grid"
mc:Ignorable="d"
d:DesignHeight="499" d:DesignWidth="688" Loaded="UserControl_Loaded"
xmlns:sdk
="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">

<
UserControl.Resources>
<
data:DepartmentCollection x:Key="Depts">
</
data:DepartmentCollection>
</
UserControl.Resources>

<
Grid x:Name="LayoutRoot" Background="White">
<
TextBlock Height="40"
HorizontalAlignment="Left" Margin="50,12,0,0"
Name="textBlock1" Text="Departments In Company" FontSize="24"
VerticalAlignment="Top" Width="563" TextAlignment="Center" />
<
sdk:DataGrid AutoGenerateColumns="False" Height="145"
Margin="50,66,0,0" HorizontalAlignment="Left"
Name="dgDept" VerticalAlignment="Top" Width="563"
DataContext="{Binding Source={StaticResource Depts}}"
ItemsSource="{Binding}" ColumnWidth="*">
<
sdk:DataGrid.Columns>
<
sdk:DataGridTextColumn
Header="DeptNo" Binding="{Binding DeptNo}">
</
sdk:DataGridTextColumn>
<
sdk:DataGridTextColumn
Header="DeptName" Binding="{Binding DeptName}">
</
sdk:DataGridTextColumn>
<
sdk:DataGridTemplateColumn>
<
sdk:DataGridTemplateColumn.CellTemplate>
<
DataTemplate>
<
Button x:Name="btnShowDetails"
Content="Show Employee Details" Width="200"
Click="btnShowDetails_Click"></Button>
</
DataTemplate>
</
sdk:DataGridTemplateColumn.CellTemplate>
</
sdk:DataGridTemplateColumn>
</
sdk:DataGrid.Columns>
</
sdk:DataGrid>


<
sdk:DataGrid AutoGenerateColumns="False" Height="156"
Name="dgEmp" HorizontalAlignment="Left" Margin="50,263,0,0"
VerticalAlignment="Top" Width="563" ColumnWidth="*"
ItemsSource="{Binding Path=Employees}">
<
sdk:DataGrid.Columns>
<
sdk:DataGridTextColumn Header="EmpNo"
Binding="{Binding EmpNo}"></sdk:DataGridTextColumn>
<
sdk:DataGridTextColumn Header="EmpName"
Binding="{Binding EmpName}"></sdk:DataGridTextColumn>
<
sdk:DataGridTextColumn Header="DeptName"
Binding="{Binding DeptName}"></sdk:DataGridTextColumn>
</
sdk:DataGrid.Columns>
</
sdk:DataGrid>
</
Grid>
</
UserControl>

The UserControl resource defines an instance for ‘DepartmentCollection’ class. This instance is then bound with the DataGrid named ‘dgDept’ (parent DataGrid). This DataGrid contains a Template Column containing ‘Button’ element. The DataGrid named ‘dhEmp’ (child DataGrid) will be used to display Employees in the Department in dgDept DataGrid.

For defining the Master-Details operations the code-behind is as shown below:

using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Collections.ObjectModel;

namespace SL4_Parent_Child_Grid
{
public partial class MainPage : UserControl
{
Department objDept;

ObservableCollection<Employee> _Employees =
new ObservableCollection<Employee>();



public ObservableCollection<Employee> Employees
{
get { return _Employees; }
set { _Employees = value; }
}

public MainPage()
{
InitializeComponent();
}

private void btnShowDetails_Click(object sender, RoutedEventArgs e)
{
objDept = dgDept.SelectedItem as Department;

var Data = from Emp in new EmployeeCollection()
where Emp.DeptName == objDept.DeptName
select Emp;
_Employees.Clear();

foreach (var item in Data)
{
_Employees.Add(item);
}
}


private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = this;
}
}
}

The above code, define ‘Employees’ collection which is Bind with the dgEmp. This collection is populated when the user lick on Show Employee Details button on the specific row.

Run the application, the result will be as below:

Silverlight Parent Child Grid






About The Author

Mahesh Sabnis is a Microsoft MVP having over 18 years of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions). He also blogs regularly at DotNetCurry.com. Follow him on twitter @maheshdotnet

No comments: