Wednesday, April 8, 2009

Working with WPF DataGrid - Part 7

The Master – Detail scenario can be displayed in WPF DataGrid using the RowDetails feature of the WPF DataGrid. For showing data in the RowDetails you need to set the RowDetailsVisibilityMode property. In our example I have set the RowDetailsVisibilityMode to be visible when the user click on a row in the Grid.

<WPF:DataGrid Name="_employeeDataGrid"

DockPanel.Dock="Top"

Grid.Row="2" Margin="12 0 12 0"

VerticalAlignment="Top"

ItemsSource="{Binding}"

AutoGenerateColumns="False" Sorting="OnGridSorting"

RowDetailsVisibilityMode="VisibleWhenSelected" SelectionMode="Extended" SelectionChanged="OnRowSelected" >

<WPF:DataGrid.RowDetailsTemplate>

<DataTemplate>

<WPF:DataGrid AutoGenerateColumns="False" GridLinesVisibility="Horizontal" Margin="20 0 0 0"

SelectionMode="Extended" RowDetailsVisibilityMode="VisibleWhenSelected" CanUserAddRows="False"

HeadersVisibility="None" ItemsSource="{Binding Path=AddressInfo}">

<WPF:DataGrid.Columns>

<WPF:DataGridTextColumn Binding="{Binding Path=Line1}" />

<WPF:DataGridTextColumn Binding="{Binding Path=Line2}" />

<WPF:DataGridTextColumn Binding="{Binding Path=State}" />

</WPF:DataGrid.Columns>

</WPF:DataGrid>

</DataTemplate>

</WPF:DataGrid.RowDetailsTemplate>

I have added Addresses to each Employee and want to show the address inside another datagrid when the employee is selected in the Grid.

The Address class contains properties to store the Address info as

public class Address

{

public int Id { get; set; }

public string Line1 { get; set; }

public string Line2 { get; set; }

public string State { get; set; }

public override bool Equals(object item)

{

Address address = item as Address;

if (address != null)

return address.Id == this.Id;

return false;

}

public override int GetHashCode()

{

return this.Id;

}

public override string ToString()

{

return String.Format("{0}, {1} \n{2}", Line1, Line2, State);

}

}

Employee class is changed to have a collection of Addresses.

public class Employee

{

public int Id { get; set; }

---

public List<Address> AddressInfo { get; set; }

}

My factory class for creating Addresses for employees

public class AddressFactory

{

private static List<Address> AddressCollection = default(List<Address>);

private static int m_Id = 0;

public static bool Remove(Address address)

{

return AddressCollection.Remove(address);

}

public static List<Address> GetAddressCollection()

{

if (AddressCollection == null)

AddressCollection = CreateCollection();

return AddressCollection;

}

private static List<Address> CreateCollection()

{

return new List<Address>

{

new Address { Id = 1, Line1 = "224 E Garden St", Line2 = "Pensacola", State = "Florida" },

new Address { Id = 2, Line1 = "770 BTM Layout", Line2 = "Bangalore", State = "Karnataka" },

new Address { Id = 3, Line1 = "40 E Chicago Ave", Line2 = "Chicago", State = "Illinos" },

new Address { Id = 4, Line1 = "800 6th Ave", Line2 = "New York", State = "NY" }

};

}

public static List<Address> GetAddress(params int[] addressIds)

{

if (AddressCollection == null)

AddressCollection = CreateCollection();

var addressCollection = from address in AddressCollection

join id in addressIds

on address.Id equals id

select address;

return addressCollection.ToList<Address>();

}

}

The CreateCollection method of the EmployeeFactory is updated to get the Addresses for each Employee

private static List<Employee> CreateCollection()

{

return new List<Employee>

{

new Employee { Id = 1, FirstName = "Prajeesh", LastName = "Prathap", Occupation = "Engineer", DateOfJoining=new DateTime(2005, 8, 1), IsContracter = false, AddressInfo = AddressFactory.GetAddress(1, 3) },

new Employee { Id = 2, FirstName = "Rahul", LastName = "Bose", Occupation = "Student", DateOfJoining=new DateTime(2009, 5, 4), IsContracter = true, AddressInfo = AddressFactory.GetAddress(1) },

new Employee { Id = 3, FirstName = "Steve", LastName = "Roberts", Occupation = "Manager", DateOfJoining=new DateTime(1994, 8, 23), IsContracter = false, AddressInfo = AddressFactory.GetAddress(4) },

new Employee { Id = 4, FirstName = "Micheal", LastName = "Clarke", Occupation = "Engineer", DateOfJoining=new DateTime(2003, 1, 14), IsContracter = true, AddressInfo = AddressFactory.GetAddress(3, 4) },

new Employee { Id = 5, FirstName = "Rachel", LastName = "Green", Occupation = "Professional", DateOfJoining=new DateTime(2006, 3, 8), IsContracter = true, AddressInfo = AddressFactory.GetAddress(2, 3) }

};

}

Output

6 comments:

Anonymous said...

Hi Prajeesh,

Very nice articles. Is there a link to download the source code for your samples?

Thanks,

Prajeesh Prathap said...

Unfortunately no. I have put the code from my sample applications while playing around with the WPF datagrid. But if you are looking for a specific sample, i can zip the file and send it to your email

Anonymous said...

Hi Prajeesh,
I have a question. I have a datagrid with RowDetailsTemplate, and work very good, but I want to insert new rows to datagrid. How can I do that? Is it possible?
Thank you very much for your articles.

Prajeesh Prathap said...

Yes, it is possible. The grid provides options for that

Brajesh Chandra said...

Hi Prajeesh,
I have a question. I have a datagrid , and work very good, but I want to that onclick of particular row ,the content should change(just below the datagrid). How can I do that? Is it possible?

Anonymous said...

Cheers!!!