【问题标题】:WPF: Implementing and binding (datagrid) to a custom collectionWPF:实现和绑定(数据网格)到自定义集合
【发布时间】:2011-07-11 04:32:36
【问题描述】:

我有一个要传递给 WPF 客户端的自定义集合,该客户端使用AutoGenerateColumns="True" 将集合绑定到datagrid。然而,数据网格显示的是空行(尽管空行的数量是正确的)。我究竟做错了什么?以下是一些示例代码。现在我已经省略了与INotifyPropertyChangedINotifyCollectionChanged 相关的所有内容,因为我首先希望在网格中显示一些数据。

我还要提一下,上面两个接口我都试过了,但是好像和这个问题没什么关系。

(您可能实际上不想查看示例代码,因为它绝对没有什么有趣的东西。集合实现只是包装了一个内部列表。)

一些随机的 POCO:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

简单的集合实现:

public class MyCollection<T> : IList<T>
{
    private List<T> list = new List<T>();

    public MyCollection()
    {
    }

    public MyCollection(IEnumerable<T> collection)
    {
        list.AddRange(collection);
    }

 #region ICollection<T> Members

    public void Add(T item)
    {
       list.Add(item);
    }

    public void Clear()
    {
       list.Clear();
    }

    public bool Contains(T item)
    {
        return list.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
       list.CopyTo(array, arrayIndex);
    }

    public int Count
    {
       get { return list.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
       return list.Remove(item);
    }

#endregion

#region IEnumerable<T> Members

    public IEnumerator<T> GetEnumerator()
    {
        return list.GetEnumerator();
    }

#endregion

#region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

#endregion

#region IList<T> Members

    public int IndexOf(T item)
    {
        return list.IndexOf(item);
    }

    public void Insert(int index, T item)
    {
       list.Insert(index, item);
    }

    public void RemoveAt(int index)
    {
       list.RemoveAt(index);
    }

    public T this[int index]
    {
       get { return list[index]; }
       set { list[index] = value; }
    }

   #endregion
} 

XAML:

<Window x:Class="TestWpfCustomCollection.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid AutoGenerateColumns="True" 
                  HorizontalAlignment="Stretch" 
                  Name="dataGrid1" VerticalAlignment="Stretch" 
                  ItemsSource="{Binding}" 
        />
    </Grid>
</Window>

窗口的代码隐藏:

public MainWindow()
{
     InitializeComponent();

     MyCollection<Person> persons = new MyCollection<Person>()
     {
         new Person(){FirstName="john", LastName="smith"},
         new Person(){FirstName="foo", LastName="bar"}
     };

     dataGrid1.DataContext = persons;
}

顺便说一句,如果您将代码隐藏更改为使用 List 而不是 MyCollection,一切都会按预期工作。

编辑:

以上代码并非取自真实情况。我发布它只是为了展示我在做什么,以测试我的问题并使其更容易复制它。 实际的自定义集合对象非常复杂,我无法在此处发布。同样,我只是想了解为了使数据网格正确绑定到自定义集合并为基础对象自动生成列需要做什么背后的基本概念。

【问题讨论】:

    标签: c# .net wpf data-binding collections


    【解决方案1】:

    显然,为了使 AutoGenerateColumns 在 WPF DataGrid 中工作,您的集合必须实现 IItemProperties,尽管我发现将我的集合包装在(Windows 窗体)BindingList 中也可以解决问题(它实际上包装了您的收藏,不像 ObservableCollection 只是将您收藏的成员复制到自身中)。

    【讨论】:

      【解决方案2】:

      我认为您通过编写来使用您的 Windows 窗体知识 dataGrid1.DataContext = 人; 在 WPF DataGrid 中连接到集合(比如 List)非常简单: dataGrid1.ItemsSource = 人员;

      【讨论】:

        【解决方案3】:

        你的MyCollection&lt;T&gt; 类型在List&lt;T&gt; 上加上了什么?无论哪种方式,我都会改用ObservableCollection(以便通知 UI 添加/删除),并在您的 Person 类上实现 INotifyPropertyChanged,以便通知 UI 该类型的属性值的更改。

        编辑

        我认为绑定到您自己的自定义集合类型并不是特别简单。您需要在该类型上实现 INotifyPropertyChangedINotifyCollectionChanged。这篇文章可能有点用 - http://www.e-pedro.com/2009/04/creating-a-custom-observable-collection-in-wpf/

        如果您使用 MVVM,另一种选择是在您的模型上使用您的自定义集合类型,并在您的视图模型上使用标准 ObservableCollection 并从您的模型中填充您的视图模型集合,然后将您的网格绑定到您的视图模型集合。

        【讨论】:

        • 对不起,我的问题可能不清楚。 MyCollection 对象仅用于描述问题。我使用的实际自定义集合完全不同。我只是想了解如何使这项工作。将更新问题。
        • 搞笑,条条大路通向同一篇文章。实际上,我确实按照您链接到的文章的指示进行了操作。这使我想到了我在问题中提到的现象。至于使用视图模型作为中介,这正是我想通过实现自己的集合来避免的。这是当前的实现,但我想减少绑定代码的数量。另外,我有意避开 INotify___ 的话题,因为我首先想看看 AutoGenerateColumns 在数据网格中是否有效。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-04-15
        • 2011-01-03
        • 1970-01-01
        • 2013-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多