2010-02-02 3 views
4

В моем коде UI У меня есть много классов с тем же основным скелетом:Рефакторинг PropertyChangedEventHandler

  • производных от INotifyPropertyChanged
  • содержит следующий код:

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

Это кажется как отличный шанс превратиться в класс и извлечь из этого вместо INotifyPropertyChanged, но, к сожалению, C# не поддерживает мульти наследование, поэтому на самом деле это не сработает. Любые идеи о том, как реорганизовать такой код?

+0

пусть topparent наследовать от вашего Notify-класса – Natrium

+0

Natrium, что будет загрязнено до многих классов, которые не имеют ничего общего с этим :( –

ответ

1

Не можете ли вы просто поместить этот код в суперкласс класса суперкласса?

  • Объект
    • Ваш конкретный NotifyPropertyChanged класс < - Вставьте здесь
      • Независимо от ViewModel, унаследованный от (и остановил вас, используя множественное наследование
        • Ваш бетон ViewModel
        • Другое бетонная модель обзора

Большинство MVVM Каркасы обеспечивают такой класс для вас.

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

+0

Да, я думаю, мне нужно сделать что-то вроде этого. Спасибо за ссылку MVVM, приятно знать, что люди знают об этом. Я просто озадачен тем, что книги о WPF (Программирование WPF) не упоминают ничего подобного. Или что WPF не имеет некоторого класса notifypropertychanged, так как он должен быть достаточно быстрым, что приводит к уродливому дублированному коду. –

+0

Но, как я писал Natrium, это действительно довольно уродливое решение, так как классы посередине смазаны чем-то, что им действительно не нужно. Я думаю, это самое лучшее, что можно сделать с ООП ;-) –

+0

Хмм. Что вы имеете в виду, что классы посередине смазаны чем-то, о чем они не должны заботиться? Каковы эти средние классы, ответственные за ваш проект? –

1

Может быть, вы можете использовать что-то вроде этого:

class A1 : INotifyPropertyChanged 
{ 
    private string _myProperty; 
    private static Expression<Func<A1, string>> myProperty = _ => _.MyProperty; 

    public string MyProperty 
    { 
     get { return _myProperty; } 
     set 
     { 
      _myProperty = value; 
      InvokePropertyChanged(myProperty); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void InvokePropertyChanged<T>(Expression<Func<A1, T>> property) 
    { 
     PropertyChangedEventHandler Handler = PropertyChanged; 
     if (Handler != null) 
     { 
      MemberExpression expression = (MemberExpression)property.Body; 
      Handler(this, new PropertyChangedEventArgs(expression.Member.Name)); 
     } 
    } 
} 

Это существенным образом снизить будущие изменения кода;)

Или вы можете использовать Postsharp plug-in that automatically implements INotifyPropertyChanged.

+0

могли бы вы добавить еще какое-то объяснение? –

+0

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

+0

@Anders: Я имею в виду, что, возможно, вместо того, чтобы извлекать из какого-то класса, вы могли бы легко сделать это вручную? Нет, есть несколько дополнительных способов: 1. генерация кода 2. отражение 3.PostSharp –

0

Это 4 строки кода, которые никогда не изменятся. Создайте фрагмент!

+1

Хотя вам может потребоваться добавить безопасность потоков: void NotifyPropertyChanged (String info) { var handler = PropertyChanged; если (обработчик! = Null) { обработчик (это, новый PropertyChangedEventArgs (info)); } } –

1

Обычной практикой является иметь базовый класс, реализующий INotifyPropertyChanged, как это:

public abstract class ViewModelBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 

     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

Тогда ваши классы извлекут из этого, и вы можете позвонить OnPropertyChanged, когда вы хотите, чтобы сообщать об изменениях по стоимости свойство:

public class PersonViewModel : ViewModelBase 
{ 

    public PersonViewModel(Person person) 
    { 
     this.person = person; 
    } 

    public string Name 
    { 
     get 
     { 
      return this.person.Name; 
     } 
     set 
     { 
      this.person.Name = value; 
      OnPropertyChanged("Name"); 
     } 
    } 
} 
0

Это, вероятно, небольшая помощь, но вы можете использовать ключевое слово Params так, чтобы вы могли изменить более одного свойства в то время.

public event PropertyChangedEventHandler PropertyChanged; 

    public void NotifyPropertiesChanged(params string[] Properties) 
    { 
     if (PropertyChanged != null) 
      foreach (string property in Properties) 
       PropertyChanged(this, new PropertyChangedEventArgs(property)); 
    } 

Это уменьшает количество линий, которые вы используете при уведомлении об изменениях свойств в будущем.Таким образом, вы используете:

NotifyPropertiesChanged ("foo", "bar");

Вместо того, чтобы:

NotifyPropertyChanged ("Foo"); NotifyPropertyChanged ("bar");

В противном случае я согласен с предложением Андерса о его перемещении по дереву наследования, вероятно, было бы лучше.

Смежные вопросы