Привязка данных 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));
}
}