Атрибут для вызова OnPropertyChanged в WPF viewmodel - PullRequest
0 голосов
/ 10 февраля 2019

В моделях представления wpf-приложения мне часто нужно объявлять свойства следующим образом:

 public string IdAnalisi5
  {
     get { return ricettaCorrente.IdAnalisi1; }
     set
     {
        ricettaCorrente.IdAnalisi5 = value;
        OnPropertyChanged(nameof(IdAnalisi5));
     }
  }

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

[PropertyChanged(nameof(IdAnalisi5)]
public string IdAnalisi5 => ricettaCorrente.IdAnalisi1; 

Очень часто можно сэкономить много кода.

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Вы можете использовать легкий инструментарий MVVM.Вам нужно будет создать подкласс для вашей модели представления из ViewModelBase, и тогда вы сможете написать что-то вроде этого:

public string IdAnalisi5
{
    get => ricettaCorrente.IdAnalisi5;
    set => Set(ref ricettaCorrente.IdAnalisi5, value);
}

Обратите внимание, что это работает, только если ricettaCorrente.IdAnalysi5 это поле, а несвойство.

MVVM Light Toolkit - не единственный инструмент, который предоставляет вам эту функциональность.Другие подобные инструменты включают Prism и Caliburn.Micro.

0 голосов
/ 10 февраля 2019

Как я уже сказал, я не знаю, как решить эту проблему с помощью «Атрибута», но существует некоторая реализация динамических шаблонов прокси, чтобы упростить использование OnPropertyChanged.

Создание прокси

    public class ProxyCreator
{
  public static T MakeINotifyPropertyChanged<T>() where T : class, new ()
  {
    //Creates a proxy generator
    ProxyGenerator proxyGen = new  ProxyGenerator();

    //Generates a proxy using our Interceptor and implementing INotifyPropertyChanged
    var proxy = proxyGen.CreateClassProxy(
      typeof (T),
      new  Type[] { typeof (INotifyPropertyChanged) },
      ProxyGenerationOptions.Default,
      new  NotifierInterceptor()
      );

    return proxy as T;
  }
}

Перехватчик , который выполняет две основные функции:

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

public class NotifierInterceptor : IInterceptor
{
  private PropertyChangedEventHandler handler;
  public static Dictionary<String, PropertyChangedEventArgs> _cache =
    new  Dictionary<string, PropertyChangedEventArgs>();

  public void Intercept(IInvocation invocation)
  {
    //Each subscription to the PropertyChangedEventHandler is intercepted (add)
    if (invocation.Method.Name == "add_PropertyChanged")
    {
      handler = (PropertyChangedEventHandler)
            Delegate.Combine(handler, (Delegate)invocation.Arguments[0]);
      invocation.ReturnValue = handler;
    }
    //Each de-subscription to the PropertyChangedEventHandler is intercepted (remove)
    else if (invocation.Method.Name == "remove_PropertyChanged")
    {
      handler = (PropertyChangedEventHandler)
         Delegate.Remove(handler, (Delegate)invocation.Arguments[0]);
      invocation.ReturnValue = handler;
    }
    //Each setter raise a PropertyChanged event
    else if (invocation.Method.Name.StartsWith("set_"))
    {
      //Do the setter execution
      invocation.Proceed();
      //Launch the event after the execution
      if (handler != null)
      {
        PropertyChangedEventArgs arg =
          retrievePropertyChangedArg(invocation.Method.Name);
        handler(invocation.Proxy, arg);
      }
    }
    else invocation.Proceed();
  }

  // Caches the PropertyChangedEventArgs
  private PropertyChangedEventArgs retrievePropertyChangedArg(String methodName)
  {
    PropertyChangedEventArgs arg = null;
    NotifierInterceptor._cache.TryGetValue(methodName, out arg);
    if (arg == null)
    {
      arg = new  PropertyChangedEventArgs(methodName.Substring(4));
      NotifierInterceptor._cache.Add(methodName, arg);
    }
    return arg;
  }
}

И наконец использование похоже на:

MyBusinessObject myBusinessObject;
DataContext = myBusinessObject = ProxyCreator.MakeINotifyPropertyChanged<MyBusinessObject>();

А также я нашел другиереализации динамического прокси, которые делают то же самое:

Реализация InotifyPropertyChanged с Castle.DynamicProxy

Я надеюсь быть полезной для вас:)

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