Какая концепция лежит в основе INotifyPropertyChanged? - PullRequest
11 голосов
/ 24 августа 2010

Во всех примерах Silverlight с использованием MVVM используется интерфейс с именем IPropertyChanged. Какова концепция этого и почему нам нужно вызывать событие всякий раз, когда мы устанавливаем какое-то значение?

Например: -

public class UserNPC:INotifyPropertyChanged
{
    private string name;
    public string Name { 
        get { return name; } 
        set { name = value; onPropertyChanged(this, "Name"); } 
    }
    public int grade;
    public int Grade { 
        get { return grade; } 
        set { grade = value; onPropertyChanged(this, "Grade"); } 
    }

    // Declare the PropertyChanged event
    public event PropertyChangedEventHandler PropertyChanged;

    // OnPropertyChanged will raise the PropertyChanged event passing the
    // source property that is being updated.
    private void onPropertyChanged(object sender, string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(sender, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Какова точная цель INotifyPropertyChanged?

Ответы [ 4 ]

15 голосов
/ 24 августа 2010

У вас есть следующие зависимости:

Вид → Связывание → Модель

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

Если некоторые данные в вашем Model объекте изменяются, вы должны вызвать событие PropertyChanged.Зачем?Поскольку объект Binding зарегистрировал метод с событием PropertyChanged объекта данных.

Поэтому все, что вам нужно сделать, когда что-то меняется в вашем объекте Model , этоподнять событие, и все готово.

Когда вы это сделаете, объект Binding получит уведомление об изменении через ваше событие.В свою очередь объект Binding позволяет объекту View знать, что что-то произошло.Затем объект View может обновить пользовательский интерфейс при необходимости.

Пример кода

Здесь у вас есть скомпилированный пример.Установите несколько точек останова, выполните код с помощью F11 и посмотрите, что происходит за кулисами.Обратите внимание, что этот пример имеет следующую зависимость: View → Model.Я оставил объект Binding.

using System;
using System.ComponentModel;

namespace INotifyPropertyChangedDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create 2 listeners.
            View1 view1 = new View1();
            View2 view2 = new View2();

            // Create 1 data object.
            Model model = new Model();

            // Connect listener with data object.
            model.PropertyChanged += new PropertyChangedEventHandler(view1.MyPropertyChangedEventHandler);
            model.PropertyChanged += new PropertyChangedEventHandler(view2.MyPropertyChangedEventHandler);

            // Let data object publish change notification.
            model.FirstName = "new name";

            // Check whether all listeners got notified.
            // ... via console.
        }

        public class Model : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;

            private string firstName;
            public string FirstName
            {
                get { return firstName; }
                set
                {
                    if (firstName != value)
                    {
                        firstName = value;
                        if (PropertyChanged != null)
                        {
                            PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
                        }
                    }
                }
            }
        }

        public class View1
        {
            public void MyPropertyChangedEventHandler(object source, PropertyChangedEventArgs arg)
            {
                Console.WriteLine("Listener 1: Changed Property: {0}", arg.PropertyName);
                string newValue = ((Model) source).FirstName;
                Console.WriteLine("Listener 1: Changed Property Value: {0}", newValue);
            }
        }

        public class View2
        {
            public void MyPropertyChangedEventHandler(object source, PropertyChangedEventArgs arg)
            {
                Console.WriteLine("Listener 2: Changed Property: {0}", arg.PropertyName);
                string newValue = ((Model)source).FirstName;
                Console.WriteLine("Listener 2: Changed Property Value: {0}", newValue);
            }
        }
    }
}
5 голосов
/ 24 августа 2010

MVVM в WPF и Silverlight реализована путем привязки элементов пользовательского интерфейса к модели представления.Однако когда модель представления изменится, как пользовательский интерфейс узнает об обновлении?

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

Например, скажем, у вас есть TextBlock, который показывает цену акций, и он привязан к свойству string Price модели представления,Модель представления, в свою очередь, использует сервис для обновления цен на акции каждые 30 секунд.Таким образом, каждые 30 секунд изменяется свойство Price: 30 секунд назад это было «29,20 доллара», теперь это «29,12 доллара», а через 30 секунд это будет «28,10 доллара».Привязка TextBlock применяется при загрузке TextBlock, но не каждый раз, когда изменяется Price.Однако, если вы реализуете INotifyPropertyChanged и вызываете событие для свойства «Price» в установщике Price, тогда TextBlock может подключиться к событию и, таким образом, «знать», когда возвращаться и «перечитывать»Price и обновите отображаемый текст.

3 голосов
/ 24 августа 2010

Большинство элементов управления Silverlight отслеживают изменения данных, которые они отображают, просто подписываясь на события PropertyChanged.

например, элемент управления делает что-то подобное за кадром:Именно поэтому ObservableCollection используется вместо более простых списков в приложениях Silverlight.Они реализуют INotifyPropertyChanged, чтобы элементы управления, отображающие коллекции, могли видеть изменения, происходящие в списке, а также в отдельных элементах списка.

0 голосов
/ 19 августа 2013

Недавно я для забавы создал 3-уровневую программу и хотел убедиться, что все части разделены настолько, насколько это возможно.

В моем графическом интерфейсе пользователь мог вводить имя по своему усмотрению, однако у моего бизнес-класса была логика для изменения всех имен на Заголовок. Это сработало, однако GUI никогда не сообщалось об этом обновлении, которое сделал бизнес-класс.

Так что моя работа в то время была простой ... но выглядела неправильно. Что-то вроде следующего

var _person = new Person();

// In some form event handler like button click
_person.Name = txtName.Text;
txt.Name.Text = _person.Name;

Это помогло обновить графический интерфейс, отделив его от бизнес-логики. Я хотел создать событие, которое сработало бы, когда бизнес-логика изменила значение по сравнению с тем, что было напечатано в GUI, и GUI прослушивал бы это событие.

Так что теперь у меня будет что-то вроде ...

var _person = new Person();

// In some form event handler like button click
_person.Name = txtName.Text;


// In the GUI class
public void OnInternalPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
    txtName.Text = _person.Name;
}

ПРИМЕЧАНИЕ. Я делаю это не для всех изменений свойств ... только для тех, которые отличаются от ожидаемых пользователем ... изменение всего строчного имени на Заголовок и показ его пользователю.

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