2012-05-04 23 views
8

Có thể đây là câu hỏi như vậy, nhưng tôi không tìm thấy nó.Tự đăng ký cuộc gọi phương thức PropertyChanged hoặc addition trong setter?

Tôi có ứng dụng MVVM và trong ViewModel Tôi phải thực hiện một số hành động bổ sung đối với các thay đổi của một số thuộc tính (ví dụ: nếu View thay đổi chúng). Cách tiếp cận nào tốt hơn trong tâm trí bạn và tại sao?

1st - Thêm AdditionalAction cuộc gọi đến setter

public class ViewModel: INotifyPropertyChanged 
{ 
    private int _MyProperty; 

    public int MyProperty 
    { 
    get { return _MyProperty; } 
    set 
    { 
     if (_MyProperty == value) return; 
     _MyProperty = value; 
     RaisePropertyChanged(() => MyProperty); 

     // --- ADDITIONAL CODE --- 
     AdditionalAction(); 
    } 
    } 
} 

2 - Tự đăng ký INotifyPropertyChanged

public class ViewModel: INotifyPropertyChanged 
{ 
    public ViewModel() 
    { 
    // --- ADDITIONAL CODE --- 
    PropertyChanged += OnPropertyChanged; 
    } 

    private int _MyProperty; 

    public int MyProperty 
    { 
    get { return _MyProperty; } 
    set 
    { 
     if (_MyProperty == value) return; 
     _MyProperty = value; 
     RaisePropertyChanged(() => MyProperty); 
    } 
    } 

    void PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
    // --- ADDITIONAL CODE --- 
    if (e.PropertyName == "MyProperty") 
     AdditionalAction(); 
    } 
} 

Hãy tưởng tượng, mà tôi không có vấn đề hiệu suất hoặc 10'000 đối tượng. Nó chỉ là View và ViewModel. Điều gì là tốt hơn? Mã đầu tiên là "nhỏ hơn" và có ít chi phí hơn, nhưng thứ hai (trong tâm trí của tôi) rõ ràng hơn và tôi có thể sử dụng đoạn mã cho mã thuộc tính tạo tự động. Thậm chí nhiều hơn - trong trường hợp thứ 2 tôi có thể viết một cái gì đó trong xử lý sự kiện như:

On.PropertyChanged(e, p => p.MyProperty, AdditionalAction); 

nơi On là đẳng cấp helper.

Vì vậy, điều gì là tốt hơn trong tâm trí của bạn và tại sao?

CẬP NHẬT:

OK, có vẻ như tôi thấy chưa một cách tiếp cận:

3 - thêm "điểm mở rộng" trong RaisePropertyChanged:

public class NotificationObject : INotifyPropertyChanged 
{ 
    void RaisePropertyChanged(Expression<...> property) 
    { 
    // ... Raise PropertyChanged event 
    if (PropertyChanged != null) 
     // blah-blah 

    // Call extension point 
    OnPropertyChanged(property.Name); 
    } 

    public virtual OnPropertyChanged(string propertyName) 
    { 
    } 
} 

public class ViewModel: NotificationObject 
{ 
    private int _MyProperty; 

    public int MyProperty 
    { 
    get { return _MyProperty; } 
    set 
    { 
     if (_MyProperty == value) return; 
     _MyProperty = value; 
     RaisePropertyChanged(() => MyProperty); 
    } 
    } 

    override OnPropertyChanged(string propertyName) 
    { 
    if (propertyName == "MyProperty") 
     AdditionalAction(); 
    } 
} 

Bằng cách này chúng tôi không sử dụng sự kiện, nhưng tất cả "hành động bổ sung" được gọi từ cùng một "điểm mở rộng". "Một nơi cho tất cả các hành động bổ sung" có tốt hơn "quy trình làm việc không minh bạch" không?

+2

http://tergiver.wordpress.com/2011/01/20/self-subscription-is-asinine/ – Tergiver

+0

sidenote: xem xét sử dụng một phương pháp helper để đưa ba dòng trong setter của tài sản của bạn một, trả về một boolean nếu thuộc tính đã thay đổi. Ngắn hơn và không trùng lặp. ví dụ 'if (RaisePropertyChanged (ref _MyProperty, value, o => o.MyProperty)) AdditionalAction();' – stijn

+0

@Tergiver sự khác biệt giữa con đường của bạn và con đường thứ 2 của tôi là gì? Chúng giống nhau - bạn viết mã bổ sung không có trong "setter" nhưng trong "event handler" - phương thức 'OnXXX' từ quan điểm này giống như tự đăng ký sự kiện. Vì vậy, từ quan điểm của bạn, câu hỏi của tôi là - "Tốt hơn là gọi' AdditionalAction' từ setter hoặc từ phương thức OnPropertyChanged? " (ngay cả khi không có phương pháp OnPropertyChanged thực sự) – chopikadze

Trả lời

3

tôi sẽ chắc chắn đi cho phương pháp đầu tiên:

  • thì rõ ràng
  • nó rõ ràng trong dòng chảy và ý định
  • nó tránh lạ (IMO) tự thuê bao

"Lợi ích" của thứ hai, cho phép bạn sử dụng các thuộc tính được tạo tự động không có giá trị độ sắc nét của luồng thực thi của trường hợp linh sam, imo.

Hy vọng điều này sẽ hữu ích.

+0

bạn nghĩ gì về cách 3? – chopikadze

+0

@chopikadze: có vẻ tốt, khiến nó * có thể * hỗ trợ tái cấu trúc mã, nếu bạn loại bỏ chuỗi: propertyName theo một cách nào đó. – Tigran

3

Đây là mẫu "thông thường". Điều này cho phép bạn đặt mã thuộc tính cụ thể bên trong phương thức OnX và cho phép các lớp dẫn xuất làm như vậy. Không cần cho một tuyên bố chuyển đổi lớn, trừ khi tất nhiên bạn là người nghe bên ngoài, nhưng đó là mệnh cho khóa học cho INotifyPropertyChanged.

public class NotificationObject : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected void FirePropertyChanged(PropertyChangedEventArgs e) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
      handler(this, e); 
    } 
} 

public class ViewModel : NotificationObject 
{ 
    private int _MyProperty1; 
    public int MyProperty1 
    { 
     get { return _MyProperty1; } 
     set 
     { 
      if (value != _MyProperty1) 
      { 
       _MyProperty1 = value; 
       OnMyProperty1Changed(new PropertyChangedEventArgs("MyProperty1")); 
      } 
     } 
    } 

    protected virtual void OnMyProperty1Changed(PropertyChangedEventArgs e) 
    { 
     FirePropertyChanged(e); 
    } 

    private int _MyProperty2; 
    public int MyProperty2 
    { 
     get { return _MyProperty2; } 
     set 
     { 
      if (value != _MyProperty2) 
      { 
       _MyProperty2 = value; 
       OnMyProperty2Changed(new PropertyChangedEventArgs("MyProperty2")); 
      } 
     } 
    } 

    protected virtual void OnMyProperty2Changed(PropertyChangedEventArgs e) 
    { 
     FirePropertyChanged(e); 
    } 
} 
+0

Cảm ơn rất nhiều sự giúp đỡ của bạn, tôi đã đánh dấu câu trả lời của @Tigran chỉ vì nó có nhiều phiếu bầu hơn, nhưng tôi thực sự đánh giá cao cuộc thảo luận của chúng tôi! – chopikadze

Các vấn đề liên quan