WPF:如何使DataGrid绑定动态列可编辑?

问题描述:

我需要将一些数据绑定到具有可变列数的DataGrid。我做了它的工作使用下面的代码:WPF:如何使DataGrid绑定动态列可编辑?

int n = 0; 
foreach (string title in TitleList) 
{ 
    DataGridTextColumn col = new DataGridTextColumn(); 
    col.Header = title; 
    Binding binding = new Binding(string.Format("DataList[{0}]", n++)); 
    binding.Mode = BindingMode.TwoWay; 
    col.Binding = binding; 
    grid.Columns.Add(col); 
} 

其中DataList的声明为:

public ObservableCollection<double> DataList { get; set; } 

和TitleList声明为:

public ObservableCollection<string> TitleList { get; set; } 

的问题是,即使我指定双向绑定,它真的是单向的。当我点击一个单元格来尝试编辑时,我得到了一个异常“'EditItem'不允许用于这个视图”。我是否错过了约束性表达中的某些东西?

P.S.我从Deborah "Populating a DataGrid with Dynamic Columns in a Silverlight Application using MVVM"找到一篇文章。但是,我很难使其适用于我的情况(具体而言,我无法使标题绑定起作用)。即使它工作,我仍然面临不一致的单元格样式的问题。这就是为什么我想知道是否可以使我的上面的代码工作 - 只需稍作调整?

编辑:我发现了另一篇文章,可能与我的问题有关:Implicit Two Way binding。看起来,如果你绑定到字符串列表使用

<TextBox Text="{Binding}"/> 

你会得到这样的错误一个TextBox“双向绑定需要路径或XPath”。但问题可以很容易地通过使用

<TextBox Text="{Binding Path=DataContext, RelativeSource={RelativeSource Self}}"/> 

<TextBox Text="{Binding .}"/> 

任何人都可以给我一个提示,如果我的问题可以用类似的方式来解决能解决吗?

+0

我编辑我的答案问题是你的收藏类型的双。 – blindmeis

你绑定到一个索引器?你能告诉我们你的DataList属性是怎么样的吗?

我前段时间做了一个索引属性。

public SomeObjectWithIndexer DataList 
{get; set;} 


public class SomeObjectWithIndexer 
{ 
     public string this 
     { 
      get { ... } 
      set { ... }//<-- you need this one for TwoWay 
     } 
} 

编辑:你不能编辑你的财产的原因是你试图编辑一个“双字段”。 解决方法之一是将您的double包装到INotifyPropertyChanged类中。

public class DataListItem 
{ 
    public double MyValue { get; set;}//with OnPropertyChanged() and stuff 
} 

那么你可以使用一个

ObservableCollection<DataListItem> 

,你可以编辑你的价值。阉指数的问题都是一样的住宿仍然存在:)

Binding binding = new Binding(string.Format("DataList[{0}].MyValue", n++)); 

EDIT2:工作示例:只是为了显示双向工作

public class DataItem 
{ 
    public string Name { get; set; } 
    public ObservableCollection<DataListItem> DataList { get; set; } 

    public DataItem() 
    { 
     this.DataList = new ObservableCollection<DataListItem>(); 
    } 
} 

包装双:

public class DataListItem 
{ 
    private double myValue; 
    public double MyValue 
    { 
     get { return myValue; } 
     set { myValue = value; }//<-- set breakpoint here to see that edit is working 
    } 
} 

用户控制数据网格

<UserControl x:Class="Wpf*.IndexCollectionDataGrid" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300"> 
<DataGrid ItemsSource="{Binding MyList}" AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" /> 
     <DataGridTextColumn Header="Index1" Binding="{Binding Path=DataList[0].MyValue, Mode=TwoWay}" /> 
     <DataGridTextColumn Header="Index2" Binding="{Binding Path=DataList[1].MyValue, Mode=TwoWay}" /> 
    </DataGrid.Columns> 
</DataGrid> 
</UserControl> 

.cs

public partial class IndexCollectionDataGrid : UserControl 
{ 
    public IndexCollectionDataGrid() 
    { 
     InitializeComponent(); 
     this.MyList = new ObservableCollection<DataItem>(); 

     var m1 = new DataItem() {Name = "test1"}; 
     m1.DataList.Add(new DataListItem() { MyValue = 10 }); 
     m1.DataList.Add(new DataListItem() { MyValue = 20 }); 

     var m2 = new DataItem() { Name = "test2" }; 
     m2.DataList.Add(new DataListItem() { MyValue = 100 }); 
     m2.DataList.Add(new DataListItem() { MyValue = 200 }); 

     this.MyList.Add(m1); 
     this.MyList.Add(m2); 

     this.DataContext = this; 
    } 

    public ObservableCollection<DataItem> MyList { get; set; } 
} 

我希望你能在这个例子中找到正确的方向。

+0

@blindmeis:谢谢你的回答。我的DataList被声明为ObservableCollection 。 – newman

+0

hmm ObservableCollection的索引总是一样的吗? – blindmeis

+0

@blindmeis:我试图通过将double转换为实现了INotifyChanged的对象并得到相同的错误。所以,我不确定它是否是索引器问题。 – newman