Почему никто не использует INotifyPropertyChanging?

Я знаю, что MVVM сильно использует INotifyPropertyChanged, но я никогда не видел использования INotifyPropertyChanging. Любая причина, по которой?

Если бы я хотел использовать это, что бы было хорошим способом интегрировать это в мою MVVM Framework? Я знаю, что вы не должны использовать MessageBox на вашем ViewModel, потому что тогда вы не можете unit test его. Итак, как можно было бы вызвать предупреждение, а затем продолжить с PropertyChange, если это применимо?

Ответ 1

Что-то, что нужно помнить о INotifyPropertyChanging, - это то, что вы не можете остановить изменение. Это просто позволяет вам записать, что произошло изменение.

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

Вы можете расширить свой ViewModelBase с помощью специальной пары "интерфейс/событие":

delegate void AcceptPendingChangeHandler(
    object sender,
    AcceptPendingChangeEventArgs e);

interface IAcceptPendingChange
{
    AcceptPendingChangeHandler PendingChange;
}

class AcceptPendingChangeEventArgs : EventArgs
{
    public string PropertyName { get; private set; }
    public object NewValue { get; private set; }
    public bool CancelPendingChange { get; set; }
    // flesh this puppy out
}

class ViewModelBase : IAcceptPendingChange, ...
{
    protected virtual bool RaiseAcceptPendingChange(
        string propertyName,
        object newValue)
    {
        var e = new AcceptPendingChangeEventArgs(propertyName, newValue)
        var handler = this.PendingChange;
        if (null != handler)
        {
            handler(this, e);
        }

        return !e.CancelPendingChange;
    }
}

В этот момент вам нужно добавить его по соглашению к вашим моделям просмотров:

class SomeViewModel : ViewModelBase
{
     public string Foo
     {
         get { return this.foo; }
         set
         {
             if (this.RaiseAcceptPendingChange("Foo", value))
             {
                 this.RaiseNotifyPropertyChanging("Foo");
                 this.foo = value;
                 this.RaiseNotifyPropretyChanged("Foo");
             }
         }
     }
}

Ответ 2

INotifyPropertyChanging - это оптимизация для использования с Linq to SQL. Когда объект реализует этот интерфейс, он использует изменяющееся событие в качестве сигнала для кэширования старого значения свойства. Если объект не реализует этот интерфейс, он всегда будет кэшировать значения свойств, увеличивая использование памяти. См. Как интерфейс INotifyPropertyChanging помогает ограничить потребление памяти для более подробной информации.

Ответ 3

Чтобы ответить на второй вопрос, вы всегда можете использовать шаблон Injection Dependency, чтобы ваша виртуальная машина полагалась на интерфейс (INotifier?) и передавала конкретную реализацию, которая вызывается MessageBoxes. Это оставляет неизменным целостность.

Изменить: Первый вопрос, вероятно, слишком субъективен для SO. Цель интерфейса понятна, но когда его использовать, это будет для очень конкретных случаев использования. Свойства зависимостей повышают что-то подобное, и может быть полезно проверить, что новое значение действительно перед его применением, но если вы используете простые свойства, вы можете просто поставить эту проверку внутри своего сеттера. Если другой компонент должен проверять достоверность, тогда обычно было бы проще, если бы этот компонент сам внес изменения (после проверки нового значения) или был явно вызван для проверки изменения компонентом, внесшим изменение.

Ответ 4

INotifyPropertyChanging запускается непосредственно перед изменением свойства. Важно, почему? Так что внешний обработчик событий может генерировать исключение и предотвращать изменение. И почему вы хотите это сделать? Когда-нибудь это может быть вашим единственным обходным путем для ошибки в кодовой базе другого кода, поэтому не нужно так быстро удалять escape-люк.

Ответ 5

Вам нужен INotifyPropertyChanged, например, если вы хотите знать, когда будет изменена любая переменная, потому что вы можете использовать PropertyChangedEventHandler. Таким образом, вы можете перезагрузить gui во время запуска программы, если какое-либо свойство зависимостей привязано к любому элементу gui.

В последнем вопросе я думаю, что вы можете написать файл журнала с определенными сообщениями, и если вы хотите показать пользователю какое-либо предупреждение, вы можете использовать элементы управления, такие как сводка ошибок или всплывающие подсказки. Но если вам это нужно только для тестирования, вы можете сохранить предупреждения с помощью блоков try и catch.