WPF Binding ListBox Master / Detail - PullRequest
       15

WPF Binding ListBox Master / Detail

4 голосов
/ 21 сентября 2011

Я могу заставить это работать с XmlDataSource, но не с моими собственными классами.Все, что я хочу сделать, - это связать список со своим экземпляром коллекции, а затем связать текстовое поле со списком, чтобы я мог редактировать имя человека (в двух направлениях).Я сознательно держал это как можно проще в надежде, что кто-нибудь сможет заполнить пробелы.

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 # код позади:

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>
    {
    }
}

Все примеры в Интернете, по-видимому, содержат статический класс, возвращающий данные, определенные кодом (например, return new Person («бла-бла»)), а не мой собственный экземпляр коллекции - в данном случае MyPeeps.Или, может быть, я не произношу правильное заклинание поиска.

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

Ответы [ 2 ]

14 голосов
/ 21 сентября 2011

Правильным способом было бы использовать шаблон MVVM и создать ViewModel, например, так:

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

Инициализируйте его в коде своего представления следующим образом:

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

И связывайтеданные примерно так:

<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>

Привязка будет работать следующим образом:

Для DataContext самого окна задан экземпляр ViewModel.Поскольку ListBox и TextBox не задают никаких DataContext, они наследуют его от Window.Привязки к объекту всегда работают относительно DataContext, если не указано ничего другого.Это означает, что привязка TextBox ищет свойство SelectedPerson в его DataContext (т.е. в MainWindowViewModel) и свойство Name в этом SelectedPerson.

БазовоеМеханизм этого примера следующий: свойство SelectedPerson в ViewModel всегда синхронизируется с SelectedItem ListBox, а свойство Text TextBox всегда синхронизируется со свойством NameSelectedPerson.

0 голосов
/ 21 сентября 2011

Попробуйте унаследовать ваш People класс от ObservableCollection<Person>

...