Как перехватить событие PropertyChanged для экземпляра объекта, который связан с SelectedItem списка - PullRequest
0 голосов
/ 28 марта 2020

Я пытаюсь изучить WPF с C#, так что терпите меня, если вопрос наивный.

  1. У меня есть класс с именем Person с 2 свойствами (FirstName, LastName) и 1 вычисляемым свойством (FullName), который реализует INotifyPropertyChanged.
  2. У меня есть ObservableCollection типа Person, который я связал с ListBox.
  3. У меня есть экземпляр Person, названный SelectedPerson, с которым я связан свойство ListBox SelectedItem.
  4. У меня есть два TextBox, которые связаны со свойствами SelectedPerson.FullName и SelectedPerson.LastName.

Пока что все работает так, как должно:

  • Нажатие (выбор) человека из ListBox обновляет экземпляр SelectedPerson, и это, в свою очередь, заполняет текстовые поля правильной информацией
  • При изменении содержимого TextBox обновляется экземпляр SelectedPerson, и это в очередь обновляет содержимое ListBox (когда отредактированный TextBox теряет фокус)
* 1 020 * То, чего я хочу достичь сейчас, это как-то прослушивать событие PropertyChanged SelectedPerson, поэтому после изменения содержимого TextBox я могу запустить некоторый код. Я хочу, чтобы код запускался один раз, после изменения связанного свойства (например, как обновляется ListBox после остановки редактирования), поэтому я не хочу слушать событие TextBox TextBox.

Могу ли я использовать событие PropertyChanged для SelectedPerson, поэтому независимо от того, какой Person является текущим SelectedItem, я могу прослушивать событие PropertyChanged или мне нужно использовать событие PropertyChanged для каждого экземпляра Person в ObservableCollection? (или ... что-то другое?)

Для справки, здесь приведены соответствующие выдержки из кода для всего вышеперечисленного

Класс Person

  public class Person : INotifyPropertyChanged
    {
       ...
       public string FirstName
        {
            get { return _firstName; }
            set { _firstName = value; OnPropertyChanged("FirstName"); OnPropertyChanged("FullName"); }
        }

        public string LastName
        {
            get { return _lastName; }
            set { _lastName = value; OnPropertyChanged("LastName"); OnPropertyChanged("FullName"); }
        }

        public string FullName { get { return $"{LastName} {FirstName}"; } }
    }

MainWindow

public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public ObservableCollection<Person> People { get; set; }

        private Person _selectedPerson;
        public Person SelectedPerson
        {
            get { return _selectedPerson; }
            set { _selectedPerson = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedPerson"));  }
        }

        public MainWindow() 
        {
            InitializeComponent();
            this.DataContext = this;
            People = new ObservableCollection<Person>
            {
                new Person { FirstName = "John", LastName = "Doe" },
                new Person { FirstName = "Jane", LastName = "Smith" }
            };
        }
    }

И элементы XAML

...
        <ListBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding Path=People}" SelectedItem="{Binding SelectedPerson, Mode=TwoWay}" DisplayMemberPath="FullName" Margin="10"/>
        <StackPanel Grid.Row="1" Grid.Column="2" Orientation="Vertical" Margin="10" VerticalAlignment="Center">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="First Name" HorizontalAlignment="Right" Margin="10"/>
                <TextBox Text="{Binding SelectedPerson.FirstName, Mode=TwoWay}" Width="120" Margin="10"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Last Name" HorizontalAlignment="Right" Margin="10"/>
                <TextBox Text="{Binding SelectedPerson.LastName, Mode=TwoWay}" Width="120" Margin="10"/>
            </StackPanel>
        </StackPanel>
...

Ответы [ 2 ]

0 голосов
/ 28 марта 2020

Могу ли я использовать событие PropertyChanged SelectedPerson, поэтому независимо от того, какой Person является текущим SelectedItem, я могу прослушивать событие PropertyChanged

Да. Но вам нужно добавить код к , а также подписаться («прослушать») на событие PropertyChanged вашего MainWindow, чтобы вы могли реагировать на изменения значения свойства SelectedPerson. То есть, когда значение этого свойства изменяется, вам необходимо отписаться от ранее установленного события Person объекта PropertyChanged и подписаться на событие для теперь установленного объекта Person.

Вы на правильном пути, предпочитая делать это на уровне модели представления вместо самого представления (например, TextBox). Чем больше вы храните все свои логи не-UI c в модели представления, тем лучше.

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

Кроме того, я обнаружил, что он лучше работает (для меня, во всяком случае) для реализации базовый класс, который просматривает объекты модели, наследует, который имеет вспомогательный метод для обновления вспомогательных полей, при необходимости поднимая PropertyChanged и предоставляя необязательный обратный вызов, чтобы позволить реагировать на изменения свойств, вместо того, чтобы фактически подписываться на событие (по крайней мере, в случаи, когда вы всегда хотите ответить… в этом конкретном примере это может не помочь, потому что вы хотите обработать событие, только когда объект Person выбран в данный момент).

0 голосов
/ 28 марта 2020

Когда TextBox изменяется, запускается его установщик связанных свойств. т.е. FirstName.set или LastName.set запускается. Вы знаете это, конечно. Вы также можете запустить дополнительный код из установщика, который будет запускаться только при изменении TextBox. Чтобы предотвратить запуск кода более одного раза, проверьте новое значение по отношению к значению вспомогательного поля и, если они совпадают, верните.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...