I\'ve a GridView
which has RowDetail
. I want to each time user clicks on the rows get some detail from database, I use Telerik GridView
I've even simplified the accepted solution. It uses the trick that from DataTemplates, you can reference static resources. And in static resources, you can use ElementName in binding.
Create a new control:
public class ElementProxy : DependencyObject
{
public DependencyObject Element
{
get { return (DependencyObject)GetValue(ElementProperty); }
set { SetValue(ElementProperty, value); }
}
public static readonly DependencyProperty ElementProperty =
DependencyProperty.Register("Element", typeof(DependencyObject), typeof(ElementProxy), new PropertyMetadata(null));
}
Put it into static resources of the DataGrid or its parent control and reference it through StaticResource:
<UserControl.Resources>
<helpers:ElementProxy Element={Binding ElementName=mainPageView} x:Key="Proxy" />
</UserControl.Resources>
(in column template:)
<DataTemplate>
<Grid DataContext={Binding Element.DataContext,Source={StaticResource Proxy}} />
</DataTemplate>
The reason for this is that WPF's and Silverlights DataGrid columns live outside the logical tree and thus make it impossible to use a binding source specified using ElementName which is common when referencing ViewModel properties such as commands from within DataGrid Template Columns. For more information about this problem see: http://blogs.msdn.com/b/jaimer/archive/2008/11/22/forwarding-the-datagrid-s-datacontext-to-its-columns.aspx
The class below act's as glue between the column and the world around it. It was written for Silverlight's built-in DataGrid but should be easy enough to adapt it for the Telerik Grid. It can be used like this:
<DataTemplate x:Key="ContactRowDetailTemplate" >
<Grid Background="Transparent"
DataContext="{Binding ParentDataGrid.DataContext.ContactStatModel,
ElementName=shim,Mode=OneTime}">
<Shims:DataGridShim x:Name="shim"/>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="Sent SMS Count" Grid.Column="0" Grid.Row="0" />
<TextBlock Text=":" Grid.Column="1" Grid.Row="0" />
<TextBlock Text="{Binding SMSCount}" Grid.Column="2" Grid.Row="0" />
</Grid>
</DataTemplate>
public class DataGridShim : FrameworkElement
{
/// <summary>
/// Initializes a new instance of the <see cref="DataGridShim"/> class.
/// prepares the ParentDataGrid property for consumption by sibling elements in the DataTemplate
/// </summary>
public DataGridShim()
{
Loaded += (s, re) =>
{
ParentDataGrid = GetContainingDataGrid(this);
};
}
/// <summary>
/// Gets or sets the parent data grid.
/// </summary>
/// <value>
/// The parent data grid.
/// </value>
public DataGrid ParentDataGrid { get; protected set; }
/// <summary>
/// Walks the Visual Tree until the DataGrid parent is found and returns it
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The containing datagrid</returns>
private static DataGrid GetContainingDataGrid(DependencyObject value)
{
if (value != null)
{
DependencyObject parent = VisualTreeHelper.GetParent(value);
if (parent != null)
{
var grid = parent as DataGrid;
if (grid != null)
return grid;
return GetContainingDataGrid(parent);
}
return null;
}
return null;
}
}