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

时间:2011-03-08 15:02:22

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

我有一个自定义集合,我将其传递给WPF客户端,该客户端使用datagrid将集合绑定到AutoGenerateColumns="True"。但是,数据网格显示空行(尽管空行数正确)。我究竟做错了什么?以下是一些示例代码。现在我省略了与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&lt; Person&gt;而不是MyCollection&lt; Person&gt;,一切都按预期工作。

编辑:

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

3 个答案:

答案 0 :(得分:4)

显然,为了让AutoGenerateColumns在WPF DataGrid中工作,你的集合必须实现IItemProperties,尽管我发现将我的集合包装在(windows窗体)BindingList中就可以了同样(它实际上包装了你的收藏,不像ObservableCollection只是将你的收藏成员复制到自己身上)。

答案 1 :(得分:3)

MyCollection<T>类型添加List<T>的内容是什么?无论哪种方式,我都会使用ObservableCollection代替(以便通知UI添加/删除),并在INotifyPropertyChanged类上实现Person,以便通知用户界面更改该类型的属性值。

修改

我认为这对您自己的自定义集合类型没有特别的微不足道的约束力。您需要在该类型上实施INotifyPropertyChangedINotifyCollectionChanged。这篇文章可能有用 - http://www.e-pedro.com/2009/04/creating-a-custom-observable-collection-in-wpf/

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

答案 2 :(得分:3)

我认为你通过写作来使用Windows Forms的知识     dataGrid1.DataContext = persons;  在WPF中,DataGrid连接到集合(比如List)非常简单:     dataGrid1.ItemsSource = persons;