WPF:实现和绑定(DataGrid)到自定义集合

6
我有一个自定义集合,我将其传递给一个WPF客户端,该客户端使用AutoGenerateColumns="True"将集合绑定到datagrid。然而,datagrid显示空行(尽管是正确数量的空行)。我做错了什么?以下是一些示例代码。暂时省略与INotifyPropertyChangedINotifyCollectionChanged相关的所有内容,因为我首先想在网格中显示一些数据。
我还应该提到,我尝试实现上述两个接口,但它们似乎与此问题无关。
(您可能实际上不想查看示例代码,因为它没有任何有趣的东西。集合实现只是包装内部List。)
一些随机的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<Person>而不是MyCollection<Person>,则一切都按预期工作。
编辑:
上面的代码不是从实际情况中提取的。 我只是发布它以展示我正在做什么来测试我的问题,并使其更容易复制。 实际的自定义集合对象非常复杂,我无法在此处发布它。 再次强调,我只是试图理解需要完成哪些基本概念,以便数据网格可以正确地绑定到自定义集合并自动生成底层对象的列。
3个回答

4

显然,在WPF DataGrid中使AutoGenerateColumns工作,您的集合必须实现IItemProperties接口,尽管我发现将我的集合包装在(Windows窗体)BindingList中也能达到同样的效果(它实际上会包装您的集合,而不像ObservableCollection只是将您的集合成员复制到它自身中)。


3

我认为你可以利用你对Windows Forms的知识,通过编写以下代码实现数据绑定: dataGrid1.DataContext = persons; 在WPF中,将DataGrid与集合(例如List)连接非常简单,只需使用以下代码: dataGrid1.ItemsSource = persons;


3
你的 MyCollection<T> 类型相对于 List<T> 有什么优势?无论哪种方式,我会使用 ObservableCollection(这样 UI 就能被通知到添加/删除),并在你的 Person 类上实现 INotifyPropertyChanged,以便 UI 能够被通知到该类型属性值的更改。 编辑 我认为绑定自定义集合类型并不是特别容易。你需要在该类型上实现 INotifyPropertyChangedINotifyCollectionChanged。这篇文章可能会有所帮助 - http://www.e-pedro.com/2009/04/creating-a-custom-observable-collection-in-wpf/
如果你正在使用MVVM,另一个选项是在你的模型上使用自定义集合类型,并在你的视图模型上使用标准的ObservableCollection,从你的模型填充你的视图模型集合,然后将你的网格绑定到你的视图模型集合。

抱歉,我可能在我的问题中没有表达清楚。MyCollection对象只是用来描述问题的。我实际使用的自定义集合完全不同。我只是想弄清楚如何使它工作。将会更新问题。 - joniba
有趣的是,所有的路都通往那篇文章。事实上,我确实按照你链接的文章中的指示去做了。这引导我提到了问题中提到的现象。至于使用视图模型作为中介,这正是我想通过实现自己的集合来避免的。这就是当前的实现方式,但我想要减少正在进行的绑定代码量。此外,我特意想避免INotify___ 的主题,因为我首先想看到AutoGenerateColumns在数据网格中是否起作用。 - joniba

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接