Привязка данных WPF с объектом коллекции

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 объект, чтобы попытаться databind в 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 (состоящий из textblock) для каждого элемента в объекте "люди" по мере его обновления из базы данных. Я также хотел бы, чтобы этот textblock привязывался к свойству "Name" объекта Person.

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

lstPeople.DataContext = objPeople;

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

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

A) как привязать элемент управления ListView к моему экземпляру объекта коллекции "люди"?

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

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

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

3 ответов


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

lstPeople.ItemsSource = objPeople; // :)

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

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

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

Edit: вот метод расширения для "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" } 
});

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

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

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

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

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

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

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

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));
    }

}