Xceed DataGrid for WPF v7.2 Documentation
Custom Detail Descriptions
Welcome to Xceed DataGrid, Editors, and 3D Views for WPF v7.2 > Xceed DataGrid for WPF > DataGrid Fundamentals > Manipulating Data > Providing, Inserting, and Removing Data > Master/Detail > Detail Descriptions > Custom Detail Descriptions

Prerequisite Knowledge
Object Model Overview: DataGridDetailDescription Class

The DataGridDetailDescription class provides information about a detail relation whose content will be displayed as the details of the data items in a grid or another detail. By default, detail descriptions are automatically created for:

Detail descriptions can also be explicitly defined by adding them to DetailDescriptions collection of their parent DataGridCollectionViewDataGridCollectionViewSource, or detail description.

Although the most common types of detail relations are automatically detected, it is also possible to create and use custom detail descriptions that will return detail items for a parent item, whatever the definition of the detail relation is. 

Creating a Detail Description

Custom detail descriptions can be created by deriving from the DataGridDetailDescription class and overriding the GetDetailsForParentItem method to return the appropriate detail items, as an IEnumerable, for the received parent item (see Example 1). In the case where there are no detail items for a parent item, an empty IEnumerable or null (Nothing in Visual Basic) must be returned.

If a detail description requires information that cannot be provided through XAML, such as a PropertyDescriptor, the Initialize method can be overridden and the information provided.

Examples

All examples in this topic assume that the grid is bound to the Employees table of a LINQ  data context, unless stated otherwise.

Example 1: Creating a custom detail description

The following example demonstrates how to create and use a custom detail description that handles LINQ detail relations, which are provided by properties to which the AssociationAttribute is applied.

VB.NET
Copy Code
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports Xceed.Wpf.DataGrid
Imports System.Reflection
Imports System.Data.Linq.Mapping
Imports System.Diagnostics
Imports System.Collections
Namespace Xceed.Wpf.Documentation
  Public Class LinqToSqlDetailDescription
               Inherits DataGridDetailDescription
    Protected Overrides Function GetDetailsForParentItem( ByVal parentCollectionView As DataGridCollectionView, _
                                                          ByVal parentItem As Object ) As IEnumerable
      Dim parentItemType As Type = parentItem.GetType()
      Dim foundProperty As PropertyInfo = Nothing
      Dim properties() As PropertyInfo = parentItemType.GetProperties()
      Dim propertyInfo As PropertyInfo
      For Each propertyInfo In properties
        Dim attributes() As Object = propertyInfo.GetCustomAttributes( Type.GetType( AssociationAttribute ), _
                                                                        False)
        If attributes.GetLength( 0 ) = 0 Then
          continue
        End If
        Dim associationAttribute As AssociationAttribute = CType( attributes( 0 ), AssociationAttribute )
        If associationAttribute.Name = Me.RelationName Then
          foundProperty = propertyInfo
          Exit Property
        End If
      Next
      If foundProperty Is Nothing Then
        Return New Object()
      Else
        Dim details As Object = foundProperty.GetValue( parentItem, Nothing )
        Dim detailsType As Type = details.GetType()
        Dim getNewBindingList As MethodInfo = detailsType.GetMethod( "GetNewBindingList" )
        Return CType( getNewBindingList.Invoke( details, Nothing), IEnumerable )
      End If
    End Function
  End Class
End Namespace
C#
Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xceed.Wpf.DataGrid;
using System.Reflection;
using System.Data.Linq.Mapping;
using System.Diagnostics;
using System.Collections;
namespace Xceed.Wpf.Documentation
{
 public class LinqToSqlDetailDescription: DataGridDetailDescription
 {
   protected override IEnumerable GetDetailsForParentItem( DataGridCollectionView parentCollectionView,
                                                           object parentItem )
   {
     Type parentItemType = parentItem.GetType();
     PropertyInfo foundProperty = null;
    
     PropertyInfo[] properties = parentItemType.GetProperties();
     foreach( PropertyInfo propertyInfo in properties )
     {
       object[] attributes = propertyInfo.GetCustomAttributes( typeof( AssociationAttribute ), false );
       if( attributes.GetLength( 0 ) == 0 )
         continue;
       AssociationAttribute associationAttribute = ( AssociationAttribute )attributes[ 0 ];
       if( associationAttribute.Name == this.RelationName )
       {
         foundProperty = propertyInfo;
         break;
       }
     }
     if( foundProperty == null )
     {
       return new object[] { };
     }
     else
     {
       object details = foundProperty.GetValue( parentItem, null );
       Type detailsType = details.GetType();
       MethodInfo getNewBindingList = detailsType.GetMethod( "GetNewBindingList" );
       return ( IEnumerable )getNewBindingList.Invoke( details, null );
     }
   }
 }
}
XAML
Copy Code
<Grid>
  <Grid.Resources>
    <xcdg:DataGridCollectionViewSource x:Key="cvs_employees"
                                       Source="{Binding Source={x:Static Application.Current},
                                                        Path=LinqDataContext.Employees}">
       <xcdg:DataGridCollectionViewSource.DetailDescriptions>
          <local:LinqToSqlDetailDescription RelationName="Employee_Employees"
                                            Title="Employees" />
          <local:LinqToSqlDetailDescription RelationName="Employee_Customer"
                                            Title="Customers">
             <local:LinqToSqlDetailDescription.DetailDescriptions>
                <local:LinqToSqlDetailDescription RelationName="Customer_Order"
                                                  Title="Orders">
                   <local:LinqToSqlDetailDescription.DetailDescriptions>
                      <local:LinqToSqlDetailDescription RelationName="Order_Order_Detail"
                                                        Title="Order Details" />
                   </local:LinqToSqlDetailDescription.DetailDescriptions>
                </local:LinqToSqlDetailDescription>
             </local:LinqToSqlDetailDescription.DetailDescriptions>
          </local:LinqToSqlDetailDescription>
       </xcdg:DataGridCollectionViewSource.DetailDescriptions>
    </xcdg:DataGridCollectionViewSource>
  </Grid.Resources>
 
  <xcdg:DataGridControl x:Name="EmployeesGrid"
                      ItemsSource="{Binding Source={StaticResource cvs_employees}}"
                      ItemsSourceName="Employee Information"
                      AutoCreateDetailConfigurations="True" />
</Grid>
VB.NET
Copy Code
Dim context As New NorthwindDataContext()
Dim collectionView As New DataGridCollectionView( context.Employees, GetType( Employee ), True, False )
collectionView.DetailDescriptions.Add( New LinqToSqlDetailDescription( "Employee_Employees", "Employees" ) )
Dim employeeCustomerDetail As New LinqToSqlDetailDescription( "Employee_Customer", "Customers" )
Dim customerOrderDetail As New LinqToSqlDetailDescription( "Customer_Order", "Orders" )
customerOrderDetail.DetailDescriptions.Add( New LinqToSqlDetailDescription( "Order_Order_Detail", "Order Details" ) )
employeeCustomerDetail.DetailDescriptions.Add( customerOrderDetail )
collectionView.DetailDescriptions.Add( employeeCustomerDetail )
dataGridControl.AutoCreateDetailConfigurations = True
dataGridControl.ItemsSourceName = "Employee Information"
dataGridControl.ItemsSource = collectionView
C#
Copy Code
NorthwindDataContext context = new NorthwindDataContext();      
DataGridCollectionView collectionView = new DataGridCollectionView( context.Employees, typeof( Employee ), true, false );      
collectionView.DetailDescriptions.Add( new LinqToSqlDetailDescription( "Employee_Employees", "Employees" ) );
LinqToSqlDetailDescription employeeCustomerDetail = new LinqToSqlDetailDescription( "Employee_Customer", "Customers" );
LinqToSqlDetailDescription customerOrderDetail = new LinqToSqlDetailDescription( "Customer_Order", "Orders" );
customerOrderDetail.DetailDescriptions.Add( new LinqToSqlDetailDescription( "Order_Order_Detail", "Order Details" ) );
employeeCustomerDetail.DetailDescriptions.Add( customerOrderDetail );
collectionView.DetailDescriptions.Add( employeeCustomerDetail );
dataGridControl.AutoCreateDetailConfigurations = true;
dataGridControl.ItemsSourceName = "Employee Information";
dataGridControl.ItemsSource = collectionView;