WPF: внедрение и привязка (datagrid) к пользовательской коллекции - PullRequest
6 голосов
/ 08 марта 2011

У меня есть пользовательская коллекция, которую я передаю клиенту WPF, который связывает коллекцию с datagrid, используя AutoGenerateColumns="True". Однако сетка данных отображает пустые строки (хотя и правильное количество пустых строк). Что я делаю неправильно? Ниже приведен пример кода. На данный момент я опускаю все, что связано с INotifyPropertyChanged и INotifyCollectionChanged, потому что, ну, во-первых, я сначала хочу, чтобы некоторые данные отображались в сетке.

Я должен также упомянуть, что я пытался реализовать вышеупомянутые два интерфейса, но они, похоже, не имеют ничего общего с этой проблемой.

(Возможно, вы на самом деле не захотите смотреть пример кода, поскольку в нем нет абсолютно ничего интересного. Реализация коллекции просто оборачивает внутренний список.)

Какой-то случайный 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;
}

Кстати, если вы измените код, чтобы использовать список вместо MyCollection , все будет работать, как и ожидалось.

EDIT:

Приведенный выше код не взят из реальной ситуации. Я только опубликовал это, чтобы показать, что я делаю, чтобы проверить мою проблему и облегчить копирование. Фактический объект пользовательской коллекции довольно сложен, и я не могу опубликовать его здесь . Опять же, я просто пытаюсь понять основную концепцию того, что нужно сделать, чтобы сетка данных правильно привязывалась к пользовательской коллекции и автоматически генерировала столбцы для базовых объектов.

Ответы [ 3 ]

4 голосов
/ 10 марта 2011

Очевидно, что для того, чтобы AutoGenerateColumns работала в WPF DataGrid, ваша коллекция должна реализовывать IItemProperties , хотя я обнаружил, что обертывание моей коллекции в BindingList (формы Windows) помогает. также (на самом деле он оборачивает вашу коллекцию, в отличие от ObservableCollection, который просто копирует членов ваших коллекций в себя).

3 голосов
/ 05 июля 2011

Я думаю, что вы используете свои знания Windows Forms, написав dataGrid1.DataContext = people;В WPF DataGrid подключается к коллекции (скажем, List) очень просто: dataGrid1.ItemsSource = person;

3 голосов
/ 08 марта 2011

Какой ваш тип MyCollection<T> добавляет более List<T>? В любом случае, я бы вместо этого использовал ObservableCollection (чтобы пользовательский интерфейс был уведомлен о добавлении / удалении) и реализовал INotifyPropertyChanged в вашем классе Person, чтобы пользовательский интерфейс получал уведомления об изменениях этого типа значения свойств.

EDIT

Не думаю, что это особенно тривиальная привязка к вашему собственному типу коллекции. Вам нужно реализовать INotifyPropertyChanged и INotifyCollectionChanged для этого типа. Эта статья может быть полезна - http://www.e -pedro.com / 2009/04 / creation-a-custom-observable-collection-in-wpf /

Другой вариант, если вы используете MVVM, - это использовать свой собственный тип коллекции на своей модели и использовать стандартный ObservableCollection для своей модели вида и заполнить свою коллекцию моделей вида из своей модели, а затем привязать свою сетку к своему виду. Коллекция моделей.

...