2011-05-25 32 views
4

下面的设计示例说明了我的问题。WPF/Xaml将DataGrid列标题和单元格绑定到不同的值

我的视图模型:

public class MyViewModel : ViewModel 
{ 
    public MyViewModel() 
    { 
     var table = new DataTable("MyDatatable"); 
     table.Columns.Add("Some Val", typeof(double)); 
     table.Columns.Add("Ref"); 

     var row = table.NewRow(); 
     row["Some Val"] = 3.14; 
     row["Ref"] = new {Title = "My Title", Description = "My Description"}; 
     table.Rows.Add(row); 

     MyDataView = table.DefaultView; 
    } 

    DataView MyDataView { get; set; } 
} 

现在我的问题在于我的XAML代码。我希望我的列标题之一是“我的标题”与相应的行值是“我的描述” ......

我的XAML:

<DataGrid ItemsSource="MyDataView" AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
    <!--This column works fine. --> 
    <DataGridTextColumn Header="Some Val" Binding="{Binding 'Some Val'}" Width="50"/> 
    <!--This column doesn't work... I'm looking for something similar to this: --> 
    <DataGridTextColumn Header="{Binding Path='Ref.Title'}" Binding="{Binding Path='Ref.Description'}"/> 
    </DataGrid.Columns> 
</DataGrid> 

这是否有道理?第二列标题应为“我的标题”,单元格值为“我的描述”。任何想法如何做到这一点?

回答

5

我相信你的第二个栏应该是:

<DataGridTextColumn Header="{Binding Path=['Ref'].Title}" 
    Binding="{Binding Path=['Ref'].Description}"/> 

编辑:

好了,它看起来像DataGridTextColumn不会从DataGrid继承的DataContext。实际上,它不是FrameworkElement或Freezable,所以它根本就没有DataContext。

该列应适用于任意数量的行,即使您只有1行。标题需要对所有行都是通用的,而绑定是特定于行的。但是,您正尝试将两者绑定到第一行。

如果您实际上有两行不同的标题,那么应该在标题中显示哪一行?

为了说明,以下工作:

public class Test { 
    public string Title { get; set; } 
    public string Description { get; set; } 
} 

public class MyViewModel { 
    public MyViewModel() { 
     var table = new DataTable("MyDatatable"); 
     table.Columns.Add("Some Val", typeof(double)); 
     table.Columns.Add("Ref", typeof(Test)); 

     var row = table.NewRow(); 
     row["Some Val"] = 3.14; 
     row["Ref"] = new Test() { Title = "My Title", Description = "My Description" }; 
     table.Rows.Add(row); 

     MyDataView = table.DefaultView; 
    } 

    public DataView MyDataView { get; set; } 
} 

随着XAML看起来像:

<DataGrid ItemsSource="{Binding MyDataView}" AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="Some Val" Binding="{Binding 'Some Val'}" Width="50" /> 
     <DataGridTextColumn Header="Test" Binding="{Binding Path=[Ref].Description}" /> 
    </DataGrid.Columns> 
</DataGrid> 

如果你定义的列时取出typeof(Test)部分,然后Path=[Ref]将把一个字符串,不是Test类型的对象。所以我不认为你可以使用匿名类型。

JP Richardson的编辑:

基于CodeNaked的回答,我想起了,我知道的解决方案,以前的一些问题,这些让我彻底解决问题。

首先,可以绑定到匿名数据类型。代码修改应为:

table.Columns.Add("Ref", typeof(object)); 

代替

table.Columns.Add("Ref"); 

作为CodeNaked说明,而不将typeof(对象)的默认对象类型被假定为一个字符串。

此外,CodeNaked声明,DataGridTextColumn不知道该行或DataGrid的DataContext。对于每一个Window对象(。典型MVVM情况下,只有一个)应该在的地方有这样的代码:

private static void RegisterDataGridColumnsToDataContext() { 
     FrameworkElement.DataContextProperty.AddOwner(typeof(DataGridColumn)); 
     FrameworkElement.DataContextProperty.OverrideMetadata(typeof(DataGrid), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits, new PropertyChangedCallback(OnDataContextChanged))); 
} 

public static void OnDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { 
     DataGrid grid = d as DataGrid; 
     if (grid != null) 
      foreach (DataGridColumn col in grid.Columns) 
       col.SetValue(FrameworkElement.DataContextProperty, e.NewValue); 
} 

然后调用“RegisterDataGridColumnsToDataContext()”显示在窗口前。

修改MyViewModel看起来像这样:

public class MyViewModel : ViewModelBase { 
    ... 
    public string ColumnTitle { get { return "My Title"; } } 
    ... 
} 

然后将改性的XAML应该是这样的:

<DataGrid ItemsSource="{Binding MyDataView}" AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
    <DataGridTextColumn Header="Some Val" Binding="{Binding 'Some Val'}" Width="50" /> 
    <DataGridTextColumn Header="{Binding (FrameworkElement.DataContext).ColumnTitle, RelativeSource={x:Static RelativeSource.Self}}" Binding="{Binding Path=[Ref].Description}" /> 
    </DataGrid.Columns> 
</DataGrid> 

注:本来,我不得不列标题标题中各个行的原因是我无法想到另一种方式将其绑定到我的DataGridTextColumn的'Header'属性。我计划每个匿名对象的'标题'属性是相同的。幸运的是,互联网盛行。

+0

它不用单引号编译。我删除了单引号,但它仍然无效。 – 2011-05-25 20:40:31

+0

@JP - 更新了我的答案。 – CodeNaked 2011-05-25 23:51:38

+0

我用完整的答案更新了答案。谢谢您的帮助。 – 2011-05-26 15:38:23

相关问题