2011-11-03 31 views
12

Tôi biết MVVM sử dụng nhiều INotifyPropertyChanged, nhưng tôi chưa bao giờ thấy bất kỳ việc sử dụng INotifyPropertyChanging nào. Có lý do gì không?Tại sao không ai sử dụng INotifyPropertyChanging?

Nếu tôi muốn sử dụng điều này, cách tốt nhất để tích hợp điều này vào Khung MVVM của tôi là gì? Tôi biết bạn không được phép sử dụng MessageBox trên ViewModel của bạn bởi vì sau đó bạn không thể kiểm tra đơn vị đó. Vì vậy, làm thế nào sẽ đi về ném lên một cảnh báo, sau đó tiếp tục với PropertyChange nếu áp dụng?

+1

Bạn muốn đạt được điều gì ở đây? Trường hợp sử dụng để biết khi nào một tài sản là * về * để thay đổi? – ChrisF

+0

Để xác minh người dùng "Bạn có chắc chắn không?" cho những thay đổi nhất định ... Chúng tôi muốn đảm bảo quản trị viên có nghĩa là thay đổi tên người dùng/thông tin đăng nhập của người dùng và họ không vô tình cập nhật trường. – michael

Trả lời

11

Điều cần ghi nhớ về INotifyPropertyChanging là bạn không thể dừng lại thay đổi xảy ra. Điều này chỉ cho phép bạn ghi lại rằng sự thay đổi đã xảy ra.

Tôi sử dụng nó trong khuôn khổ của tôi để theo dõi thay đổi, nhưng nó không phải là một phương pháp thích hợp để tạm dừng thay đổi.

Bạn có thể mở rộng ViewModelBase của bạn với một cặp giao diện tùy chỉnh/sự kiện:

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; 
    } 
} 

Tại thời điểm này, bạn sẽ cần phải thêm nó theo quy ước để xem các mô hình của bạn:

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"); 
      } 
     } 
    } 
} 
1

Để trả lời câu hỏi thứ hai, bạn luôn có thể sử dụng mẫu Dependency Injection để làm cho máy ảo của bạn dựa vào một giao diện (INotifier?) Và vượt qua một triển khai cụ thể bật lên MessageBoxes. Điều này làm cho khả năng kiểm tra đơn vị còn nguyên vẹn.

Chỉnh sửa: Câu hỏi đầu tiên có lẽ quá chủ quan đối với SO. Mục đích của giao diện là rõ ràng nhưng khi sử dụng nó sẽ cho các trường hợp sử dụng rất cụ thể. Các thuộc tính phụ thuộc nâng cao điều gì đó tương tự và nó có thể hữu ích để kiểm tra giá trị mới là hợp lệ trước khi áp dụng nó, nhưng nếu bạn đang sử dụng các thuộc tính đơn giản thì bạn có thể đơn giản đặt kiểm tra này bên trong setter của bạn. Nếu một thành phần khác cần kiểm tra tính hợp lệ thì nó sẽ đơn giản hơn nếu thành phần đó tự thay đổi (sau khi xác nhận giá trị mới) hoặc được gọi một cách rõ ràng để xác nhận sự thay đổi của thành phần tạo ra thay đổi.

-6

Bạn cần INotifyPropertyChanged ví dụ nếu bạn muốn biết khi nào bất kỳ biến nào sẽ được thay đổi bởi vì bạn có thể sử dụng PropertyChangedEventHandler. Bằng cách này bạn có thể tải lại gui trong khi chạy chương trình nếu bất kỳ thuộc tính phụ thuộc nào bị ràng buộc ở bất kỳ phần tử gui nào.

Đối với câu hỏi cuối cùng tôi nghĩ bạn có thể viết tệp nhật ký với các thư đã xác định và nếu bạn muốn hiển thị cho người dùng bất kỳ cảnh báo nào, bạn có thể sử dụng các điều khiển như tóm tắt lỗi hoặc chú giải công cụ. Nhưng nếu bạn chỉ cần điều này để thử nghiệm bạn có thể giữ cho các cảnh báo dưới với thử và bắt khối.

+1

OP hỏi về giao diện 'INotifyPropertyChanging', không phải là 'INotifyPropertyChanged' –

+1

Bỏ qua sai lầm vô tội của giao diện sai, xóa các tệp nhật ký trong trường hợp này và thử/bắt ngoại lệ không tồn tại để xác thực thuộc tính. – JRoughan

1

INotifyPropertyChanging được gọi ngay trước khi thay đổi thuộc tính. Quan trọng tại sao? Vì vậy, một xử lý sự kiện bên ngoài có thể ném một ngoại lệ và ngăn chặn sự thay đổi. Và tại sao bạn muốn làm điều đó? Một ngày nào đó nó có thể là giải pháp duy nhất của bạn để một lỗi trong cơ sở mã của người khác, do đó, không được như vậy nhanh chóng để loại bỏ các cửa thoát hiểm.

+5

Ném một ngoại lệ trong một trình xử lý sự kiện để kết thúc việc thực hiện các sự kiện firer tấn công tôi như một mùi mã lớn, bao gồm cả tùy chọn để làm điều này * chỉ trong trường hợp * tấn công tôi tồi tệ hơn. –

3

INotifyPropertyChanging là một tối ưu hóa để sử dụng với LINQ to SQL. Khi một đối tượng thực hiện giao diện này, nó sử dụng sự kiện thay đổi làm tín hiệu để lưu trữ giá trị cũ của thuộc tính. Nếu đối tượng không thực hiện giao diện này, thì nó sẽ luôn lưu trữ các giá trị thuộc tính, tăng mức sử dụng bộ nhớ. Xem How does INotifyPropertyChanging interface helps limit memory consumption để biết thêm chi tiết.

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