2011-07-25 6 views
0

私はを持っています。これはRowDetailです。ユーザーがデータベースの行をクリックするたびに、Telerik GridViewを使用します。通常の方法では、それは可能ではありません、または少なくとも私はのグリッドに直接バインドされたDataContextのGridRowに含まれているもの以上のものがあります。私が見つけたのは、UserControlという名前でRowDetailTemplate DataContextをUserControlに設定できるため、RowDetailを他のモデルに参照できるようになります。 私のコードは、このSilverlightデータバインディングエラー

<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の列が論理ツリーの外側にあるため、DataGrid Template Columns内のコマンドなどのViewModelプロパティを参照するときに一般的なElementNameを使用して指定されたバインディングソースを使用できなくなるためです。この問題の詳細については、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

Oliverさん、本当にありがとうございます。このクラスをもっと詳しく使用する方法を説明できますか? ?!! – saber

+0

私は、使用例を更新して、独自のデータ・テンプレートを使用して物事をより明確にしました。これはShimクラスをTelerikグリッドに移植した後に動作するはずですが、私はそれをテストしていません。 –

+0

Oliverさん、本当にありがとうございます。 – saber

3

私は受け入れた解決法をさらに単純化しました。それは、DataTemplatesからのトリックを使用して、静的リソースを参照することができます。静的リソースでは、バインディングにElementNameを使用できます。

  1. 新しいコントロールを作成します。データグリッドまたは親コントロールの静的リソースにそれを入れて、StaticResourceを通してそれを参照する

    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. を:

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

(中列テンプレート:)

<DataTemplate> 
     <Grid DataContext={Binding Element.DataContext,Source={StaticResource Proxy}} /> 
    </DataTemplate> 
関連する問題