«Мягкое обновление» DependencyProperties? - PullRequest
1 голос
/ 17 ноября 2011

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

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

Я посмотрел насвойств зависимостей, но не смог найти ничего, что позволило бы вам выполнить «мягкое обновление»: сообщите пользовательскому интерфейсу, что свойство изменилось, но избегайте вызова всего кода, который обычно запускается, когда пользовательский интерфейс вызывает изменение в модели представления.

Есть ли какой-нибудь способ, которым я могу получить систему свойств, которая позволяет мягкие обновления и ловит проблемы уведомления во время компиляции?

Ответы [ 2 ]

3 голосов
/ 17 ноября 2011

Мне нравится решение Foson для «раннего связывания» с именами свойств и исключения необходимости хранить строковую копию названия вашего свойства. Это ядро ​​реализации, которую я лично использую:

    public virtual string GetName<T>(Expression<Func<T>> expression)
    {
        return GetMemberName(expression);
    }

    /// <summary>Abstraction for actually finding the name of the target of the expression</summary>
    private static string GetMemberName<T>(Expression<Func<T>> expression)
    {
        if (expression != null)
        {
            var myMemberExpression = expression.Body as MemberExpression;
            if (myMemberExpression != null && myMemberExpression.Member != null)
            {
                return myMemberExpression.Member.Name;
            }
        }
        return string.Empty;
    }

Этот код находится в классе NameResolver, который мой класс ViewModelBase переносит на

  NotifyChange(Expression<Func<T>> expression)

Тогда код клиента выглядит примерно так:

private int _myBindable;
public int MyBindable { get { return _myBindable; } set { _myBindable = value; NotifyChange(() => MyBindable); }

Что касается понятия отделения уведомления GUI от обновления базового содержимого, вы можете вызывать эти методы NotifyChange () где-то еще, кроме установщика свойств, когда все, что происходит в вашем коде, должно вызвать обновление UI. Итак, GUI устанавливает ваше свойство, которое запускает некоторую логику, но вы не генерируете там уведомление об изменении - вы поднимаете его из любого места, в частности, вы хотите проинформировать пользовательский интерфейс о чем-то.

3 голосов
/ 17 ноября 2011

Если основной проблемой являются ошибки в имени свойства, существуют решения во время компиляции, например, превращение параметра «имя свойства» в дерево выражений вместо строки.

http://michaelsync.net/2009/04/09/silverlightwpf-implementing-propertychanged-with-expression-tree

Библиотека Caliburn.Micro также включает этот подход в свой класс PropertyChangedBase.

...