MVVM использует INotifyPropertyChanged Model, не уведомляя ViewModel - PullRequest
4 голосов
/ 14 сентября 2011

Я пытаюсь использовать MVVM впервые. У меня есть приложение для Windows Phone (Mango), в котором есть класс модели, класс модели представления и страница представления xaml. У меня есть элементы управления (текстовые поля), связанные с виртуальной машиной, а виртуальная машина связана с моделью.

И модель, и модель представления реализуют INotifyPropertyChanged. Реализация, которую я использую, скопирована, чтобы я мог попытаться выяснить, что я делаю с INPC. Вот код, который указан в обоих классах:

public event PropertyChangedEventHandler PropertyChanged;

private void NotifyPropertyChanged(String info)
{
   if (PropertyChanged != null)
   {
      PropertyChanged(this, new PropertyChangedEventArgs(info));
   }
}

У меня есть одно свойство в классе Model, которое можно установить вручную (из текстового поля) или рассчитать (изменив одно из других свойств). Давайте назовем это одним результатом.

Если я изменяю одно из других свойств и перехожу, INPC вызывается как в измененном свойстве, так и в пересчитанном свойстве в классе Model, хотя PropertyChanged равно null, поэтому часть кода пропускается , Затем в виртуальной машине измененное свойство проходит через INPC этого класса (как часть метода доступа set), и на этот раз PropertyChanged не является null, поэтому вызывается метод PropertyChanged. Однако для свойства Result INPC не вызывается (в этом свойстве INPC не вызывается средством доступа set другого свойства).

Вот одно из свойств в Модели, которое не является вычисляемым свойством:

public int AgeSetting
{
   get
   {
      return (int)GetValueOrDefault(AgeSettingKeyName, AgeSettingDefault);
   }
   set
   {
      AddOrUpdateValue(AgeSettingKeyName, value);
      Calculate();
   }
}

Вот свойство Расчетного значения в Модели.

public int PointsSetting
{
   get
   {
      return (int)GetValueOrDefault(PointsSettingKeyName, PointsSettingDefault);
   }
   set
   {
      AddOrUpdateValue(PointsSettingKeyName, value);
   }
}

Из ViewModel, здесь оба свойства:

public int Age
{
   get
   {
      return person.AgeSetting;
   }
   set
   {
      person.AgeSetting = value;
      NotifyPropertyChanged("Age");
   }
} 

public int PointsAllowed
{
   get
   {
      return person.PointsSetting;
   }
   set
   {
      person.PointsSetting = value;
      NotifyPropertyChanged("PointsAllowed");
   }
}

Никогда прежде этого не делал, я ожидал, что INPC должен вырасти из класса модели, в класс VM, в интерфейс пользователя. Похоже, что это не работает.

Я знаю, что свойство Result (рассчитывается) изменяется, так как я могу уйти со страницы и вернуться, и вновь отображаемое значение является правильным. Я просто не знаю, как перейти от вычисленного значения в модели к модели представления и до представления.

Спасибо за любые предложения.

Ответы [ 4 ]

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

Если значение вычисляемого свойства изменяется, также вызовите событие PropertyChanged для этого свойства. Это означает, что при изменении одного свойства могут возникнуть события для нескольких свойств.

Кроме того, если это возможно / разумно в вашем дизайне, вы можете привязать напрямую к свойствам модели и сделать Model свойством вашей ViewModel. Это значительно снижает обслуживание кода.

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

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

Учитывая класс с тремя свойствами - Score, Multiplier и Total - где Total зависит от значений Score и Multiplier, я могу написать класс следующим образом:

public class ViewModel
{
    private int score;
    public int Score
    {
        get
        {
            return this.score;
        }
        set
        {
            if (this.score != value)
            {
                this.score = value;
                // Notify that this property has changed
                NotifyOfPropertyChange(() => this.Score);
                // Notify that a dependant property has changed
                NotifyOfPropertyChange(() => this.Total);
            }
        }
    }

    private int multiplier;
    public int Multiplier
    {
        get
        {
            return this.multiplier;
        }
        set
        {
            if (this.multiplier != value)
            {
                this.multiplier = value;
                // Notify that this property has changed
                NotifyOfPropertyChange(() => this.Multiplier);
                // Notify that a dependant property has changed
                NotifyOfPropertyChange(() => this.Total);
            }
        }
    }

    public int Total
    {
        get
        {
            return this.Score * this.Multiplier;
        }
    }
}

Например, вы заметите, что когда я устанавливаю значение Score, я уведомляю об изменении как Score, так и Total. Ваше конкретное применение NotifyOfPropertyChange будет отличаться от моего, но основная идея та же. Поскольку Total является свойством, зависящим от значений других свойств, он никогда не уведомляет. Вместо этого за уведомление отвечают свойства, от которых зависит Total.

1 голос
/ 15 сентября 2011

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

public class ViewModel : INotifyPropertyChanged
{
   // Stuff
}

public class Model : INotifyPropertyChanged
{
   // Stuff
}

Также проверьте мой блог здесь о некоторых материалах MVVM. У меня есть несколько уроков, а также несколько способов запуска Inotify без использования строковых значений (используйте отражение).

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

В модели в установщике вычисляемого свойства вызывается метод NotifyPropertyChanged.Некоторая логика в вашем приложении должна обновлять модель.Убедитесь, что ViewModel подписан на это событие.Это очень важно, поскольку я думаю, что это именно то, чего вам здесь не хватает.

Затем в EventHandler в ViewModel, который был подписан на событие Models on PropertyChanged, измените соответствующее значение свойства ViewModelздесь метод в модели представления обновляет свойство в модели представления), с которым связан пользовательский интерфейс.

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