Привязка данных WPF с объектом коллекции - PullRequest
8 голосов
/ 27 мая 2010

Argh, хотя я гуглил, я был бы очень признателен, если бы кто-то мог разобрать мою проблему, так как все примеры кода в Интернете сбивают меня с толку больше, чем помощь (возможно, уже поздно) ...

У меня есть простой класс, определенный ниже:

public class Person
{
    int _id;
    string _name;

    public Person()
    { }

    public int ID
    {
        get { return _id; }
        set { _id = value; }
    }

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
}

, который хранится в базе данных, и через немного больше кода я поместил его в объект ObservableCollection, чтобы позже попытаться связать данные в WPF:

 public class People : ObservableCollection<Person>
{
    public People() : base() { }

    public void Add(List<Person> pListOfPeople)
    {
        foreach (Person p in pListOfPeople) this.Add(p);
    }
}

В XAML у меня есть ListView, который я хотел бы заполнить ListViewItem (состоящий из текстового блока) для каждого элемента в объекте «Люди», когда он обновляется из базы данных. Я также хотел бы, чтобы этот текстовый блок связывался со свойством «Имя» объекта Person.

Сначала я подумал, что смогу сделать это:

lstPeople.DataContext = objPeople;

где lstPeople - это мой элемент управления ListView в моем XAML, но это, конечно, ничего не делает. Я нашел в Интернете множество примеров, когда люди через XAML создают объект, а затем связываются с ним через свой XAML; но не тот, где мы привязываемся к созданному объекту и перерисовываем соответственно.

Может кто-нибудь дать мне несколько советов:

A) Как связать элемент управления ListView с моим экземпляром объекта People?

B) Как я могу применить шаблон к моему ListView, чтобы отформатировать его для объектов в коллекции?

Буду признателен даже за ссылки на достойный пример (ни одна из которых не работает с объектом, объявленным в XAML, пожалуйста).

Спасибо за ваше время.

Ответы [ 3 ]

7 голосов
/ 27 мая 2010

Вы были так близко.

lstPeople.ItemsSource = objPeople; // :)

Единственное, что вам нужно, это как применить представление для каждого элемента в вашей коллекции. Нет проблем. Я не буду использовать ListView ... Я просто буду использовать ItemsControl, потому что он немного проще.

<ItemsControl x:Name="lstPeople">
    <ItemsControl.ItemTemplate>
         <DataTemplate>
              <TextBlock Text="{Binding Name}" />
         </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Вот и все. Стратегия та же для Listview, но вам нужно предоставить чуть больше XAML для обеспечения заголовков столбцов и прочего. Я не уверен на 100%, что вам это нужно в данный момент, поэтому я оставил это.

Редактировать: Вот метод расширения для "AddRange", который будет делать то, что вы пытаетесь сделать, используя подкласс ObservableCollection. Немного проще ... особенно если у вас много типов коллекций (вы будете)

public static void AddRange<T>(this ObservableCollection<T> collection, IEnumerable<T> items)
{
     foreach(var item in items)
     {
          collection.Add(item);
     }
}

Тогда вы можете просто сделать:

ObservableCollection<Person> peeps = new ObservableCollection<Person>();
peeps.AddRange(new List<Person>
{ 
     new Person() { Name = "Greg" }, 
     new Person() { Name = "Joe" } 
});
0 голосов
/ 27 мая 2010

Действительно, ответ Андерсона Имеса правильный (upvote), хотя у меня есть два замечания:

Во-первых, если вам нужно отобразить только одно свойство объекта, я думаю, что проще и понятнее использовать ListBox вместо ListView, потому что код для привязки свойства будет уменьшен до

<ListBox x:Name="lstPeople" DisplayMemberPath="Name" />

Во-вторых, если вы используете WPF и Binding, убедитесь, что ваши объекты реализуют INotifyPropertyChanged , чтобы изменения всегда синхронизировались между пользовательским интерфейсом и объектами.

public class Person : INotifyPropertyChanged
{
    int _id;
    string _name;

    public Person()
    { }

    public int ID
    {
        get { return _id; }
        set { 
             _id = value; 
             RaisePropertyChanged("ID");
            }
    }

    public string Name
    {
        get { return _name; }
        set { 
             _name = value;  
             RaisePropertyChanged("Name");
            }
    }

    pivate void RaisePropertyChanged(string propName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }

}
0 голосов
/ 27 мая 2010

@ Андерсон опередил меня на несколько секунд, мой ответ был очень похож.

Я добавлю одну вещь: нет необходимости определять новый тип коллекции, которая наследуется от ObservableCollection, вместо этого вы можете просто сделать это:

ObservableCollection<Person> myPeopleCollection = new ObservableCollection<Person>();

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

...