2011-07-25 34 views
0

我有GridView它有RowDetail。我想每次用戶點擊行時都會從數據庫中獲得一些細節,我使用Telerik GridView。以正常的方式,這是不可能的,或者至少我不知道如何,因爲RowDetail上下文直接綁定到網格DataContext,我想要的比GridRow包含的更多。我發現也許我可以通過命名UserControl來將RowDetailTemplate DataContext設置爲UserControl,以便我可以將RowDetail引用到其他模型。 我的代碼是這樣Silverlight DataBinding Error

<UserControl 
    x:Name="mainPageView" 
    x:Class="Project.Client.TestView" 
    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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.GridView" 
    mc:Ignorable="d" 
    d:DesignHeight="300" d:DesignWidth="400"> 

    <UserControl.Resources> 
     <DataTemplate x:Key="ContactRowDetailTemplate" > 
      <Grid Background="Transparent" 
       DataContext="{Binding DataContext.ContactStatModel, 
       ElementName=mainPageView,Mode=OneTime}"> 
       <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> 
    </UserControl.Resources> 

    <telerik:RadGridView 
     x:Name="gridView" 
     AutoGenerateColumns="False" Height="Auto" Grid.Row="3" 
     ItemsSource="{Binding VOutboxList, Mode=TwoWay}" 
     SelectedItem="{Binding VOutboxModel, Mode=TwoWay}" 
     RowDetailsTemplate="{StaticResource ContactRowDetailTemplate}" 
     LoadingRowDetails="gridView_LoadingRowDetails"> 
     <telerik:RadGridView.Columns> 
      <telerik:GridViewDataColumn UniqueName="FirstName" Header="First Name" Width="150" /> 
      <telerik:GridViewDataColumn UniqueName="LastName" Header="Last Name" Width="150" /> 
     </telerik:RadGridView.Columns> 
    </telerik:RadGridView> 

</UserControl> 

但這次我得到這個例外

{Error: System.Exception: BindingExpression_CannotFindElementName} 

任何意見將是有益的。 最好的問候。

回答

3

原因是WPF和Silverlight DataGrid列位於邏輯樹之外,因此無法使用ElementName指定的綁定源,這在引用ViewModel屬性(如DataGrid模板列中的命令)時很常見。有關此問題的更多信息,請參閱:http://blogs.msdn.com/b/jaimer/archive/2008/11/22/forwarding-the-datagrid-s-datacontext-to-its-columns.aspx

下面的類充當列和周圍的世界之間的粘合劑。它是爲Silverlight內置的DataGrid編寫的,但應該很容易適應Telerik Grid。它可以這樣使用:

<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; 
    } 
} 
+0

非常感謝你奧利弗,但你能解釋我應該如何更詳細地使用這個類?!! ?!! – saber

+0

我已經更新了使用示例以使用您自己的數據模板來使事情更清晰。在將Shim類移植到Telerik Grid之後,這個_should_應該工作,但我沒有對它進行測試。 –

+0

非常感謝奧利弗。 – saber

3

我甚至簡化了接受的解決方案。它使用來自DataTemplates的技巧,可以引用靜態資源。而在靜態資源中,您可以在綁定中使用ElementName。

  1. 創建一個新的控制:

    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)); 
    } 
    
  2. 把它放到DataGrid中或其母公司控制的靜態資源和引用它通過靜態資源:

    <UserControl.Resources> 
        <helpers:ElementProxy Element={Binding ElementName=mainPageView} x:Key="Proxy" /> 
    </UserControl.Resources> 
    

(以列模板:)

<DataTemplate> 
     <Grid DataContext={Binding Element.DataContext,Source={StaticResource Proxy}} /> 
    </DataTemplate>