【问题标题】:WPF: How to make DataGrid binding with dynamic columns editable?WPF:如何使 DataGrid 绑定与动态列可编辑?
【发布时间】:2011-08-23 19:10:57
【问题描述】:

我需要将一些数据绑定到具有可变列数的 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; }

问题是,即使我指定了 TwoWay 绑定,它实际上是单向的。当我单击单元格尝试编辑时,出现异常“此视图不允许'EditItem'”。我只是错过了绑定表达式中的某些内容吗?

附:我找到了 Deborah "Populating a DataGrid with Dynamic Columns in a Silverlight Application using MVVM" 的一篇文章。但是,我很难让它适用于我的情况(具体来说,我无法使标题绑定工作)。即使它有效,我仍然面临单元格样式不一致等问题。这就是为什么我想知道我是否可以使上面的代码工作 - 稍微调整一下?

编辑:我发现了另一个可能与我的问题有关的帖子:Implicit Two Way binding。它看起来是否使用

将字符串列表绑定到 TextBox
<TextBox Text="{Binding}"/>

您将收到类似“双向绑定需要路径或 XPath”的错误。但是使用

可以很容易地解决这个问题
<TextBox Text="{Binding Path=DataContext, RelativeSource={RelativeSource Self}}"/>

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

如果我的问题可以用类似的方式解决,谁能给我一个提示?

【问题讨论】:

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

标签: wpf binding datagrid two-way


【解决方案1】:

您是否绑定到索引器?你能告诉我们你的 DataList 属性是什么样子的吗?

我不久前对索引属性做了同样的事情。

 public SomeObjectWithIndexer DataList
 {get; set;}


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

编辑:您无法编辑属性的原因是您尝试编辑“双字段”。 一种解决方法是使用 INotifyPropertyChanged 将你的 double 包装到一个类中。

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="WpfStackoverflow.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; }
}

我希望您通过这个示例找到正确的方向。

【讨论】:

  • @blindmeis:感谢您的回答。我的 DataList 被声明为 ObservableCollection.
  • hmm ObservableCollection 的索引是否始终相同?
  • @blindmeis:我尝试了您的建议,将 double 转换为 INotifyChanged 实施的对象,并得到了相同的错误。所以,我不确定是不是索引器问题。
  • @blindmeis:您的示例代码有效,它帮助我找出了我的问题。我的问题是 DataGrid 的绑定 DataContext 是由 linq 表达式过滤的,所以它是只读的。我希望错误可以更具体,它会为我节省很多时间。顺便说一句,它也可以直接与 ObservableCollection 一起使用。谢谢一百万!
  • 不错的一个 :) 顺便说一句,如果您使用 Snoop,您会更快地发现绑定错误
猜你喜欢
  • 2014-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-04
  • 2017-12-11
相关资源
最近更新 更多