WPF ListBox Master / Detail Binding List

I can get this to work with XmlDataSource, but not with my own classes. All I want to do is associate the list with my collection instance, and then associate the text box with the list so that I can edit the person’s name (in two directions). I intentionally kept this as simple as possible in the hope that someone could fill in the blanks.

XAML:

<Window x:Class="WpfListTest.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfListTest" Title="Window1" Height="300" Width="600"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="160"/> <ColumnDefinition Width="3"/> <ColumnDefinition Width="1*"/> </Grid.ColumnDefinitions> <DockPanel Grid.Column="0"> <ListBox /> </DockPanel> <DockPanel Grid.Column="2"> <StackPanel> <Label>Name</Label> <TextBox /> </StackPanel> </DockPanel> </Grid> </Window> 

C # code behind:

 namespace WpfListTest { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { public People MyPeeps = new People(); public Window1() { InitializeComponent(); MyPeeps.Add(new Person("Fred")); MyPeeps.Add(new Person("Jack")); MyPeeps.Add(new Person("Jill")); } } public class Person { public string Name { get; set; } public Person(string newName) { Name = newName; } } public class People : List<Person> { } } 

All the examples on the Internet seem to have what is actually a static class returning data defined by code (for example, returning a new Person (“blah blah”), and not my own collection instance - in this case MyPeeps. Or maybe I don’t cast the right search spell.

One fine day, I could make a sudden breakthrough in understanding this mandatory material, but at the moment it puzzled me. Any help was appreciated.

+4
source share
2 answers

The correct way is to use the MVVM template and create the ViewModel as follows:

 public class MainWindowViewModel : INotifyPropertyChanged { private People _myPeeps; private Person _selectedPerson; public event PropertyChangedEventHandler PropertyChanged; public People MyPeeps { get { return _myPeeps; } set { if (_myPeeps == value) { return; } _myPeeps = value; RaisePropertyChanged("MyPeeps"); } } public Person SelectedPerson { get { return _selectedPerson; } set { if (_selectedPerson == value) { return; } _selectedPerson = value; RaisePropertyChanged("SelectedPerson"); } } private void RaisePropertyChanged(string propertyName) { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } 

Initialize it in your view code like this:

 public partial class MainWindow : Window { private readonly MainWindowViewModel _viewModel; public MainWindow() { _viewModel = new MainWindowViewModel(); _viewModel.MyPeeps = new People(); _viewModel.MyPeeps.Add(new Person("Fred")); _viewModel.MyPeeps.Add(new Person("Jack")); _viewModel.MyPeeps.Add(new Person("Jill")); DataContext = _viewModel; InitializeComponent(); } } 

And bind the data like this:

 <Window x:Class="WpfApplication3.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> <Grid.ColumnDefinitions> <ColumnDefinition Width="160" /> <ColumnDefinition Width="3" /> <ColumnDefinition Width="1*" /> </Grid.ColumnDefinitions> <DockPanel Grid.Column="0"> <ListBox SelectedItem="{Binding SelectedPerson}" DisplayMemberPath="Name" ItemsSource="{Binding MyPeeps}" /> </DockPanel> <DockPanel Grid.Column="2"> <StackPanel> <Label>Name</Label> <TextBox Text="{Binding SelectedPerson.Name}" /> </StackPanel> </DockPanel> </Grid> </Window> 

Binding will work as follows:

An instance of ViewModel is installed in the DataContext of the window itself. Since the ListBox and TextBox do not indicate any DataContext , they inherit it from the window. Bindings on an object always work relative to a DataContext if nothing is specified. This means that the TextBox binding looks for the SelectedPerson property in its DataContext (i.e. In MainWindowViewModel ) and for the Name property in that SelectedPerson .

The basic mechanics of this sample are as follows: The SelectedPerson property in the ViewModel is always synchronized with the SelectedItem of the ListBox , and the Text TextBox property is always synchronized with the Name SelectedPerson property.

+13
source

Try to inherit your People class from ObservableCollection<Person>

0
source

All Articles