2011-11-29 29 views
17

Trong ViewModel MVVM của tôi, tôi có lĩnh vực nhưlàm thế nào để thực hiện int quan sát trong wpf ViewModel?

public int Delta { get; private set; } 

Tuy nhiên khi tôi cập nhật nó như thế:

Delta = newValue; 

UI không phải là làm mới.

Tôi đã nghĩ rằng databinding sẽ làm điều đó cho tôi. Ví dụ tôi có thể khai báo bộ sưu tập là ObservableCollection và sau đó dữ liệu sẽ hoạt động.

Tuy nhiên, không có ObservableInt, cách nói Chế độ xem cần phải làm mới sau đó?

Có lẽ tôi nên tăng một số sự kiện "thông báo cho tài sản đã thay đổi" hoặc điều gì đó?

+0

Có, bạn đang đi đúng hướng. Bạn cần phải nâng cao sự kiện đã thay đổi thuộc tính. google INotifyPropertyChanged –

+0

nhưng cách Chế độ xem sẽ biết rằng khi một số thuộc tính được nâng lên thì một số điều khiển nhất định cần được nâng cấp? – javapowered

+0

Chế độ xem sẽ biết điều đó thông qua các ràng buộc mà bạn có. – BigL

Trả lời

31

Bạn có hai lựa chọn:

  1. Thực hiện giao diện INotifyPropertyChanged về lớp học của bạn.
  2. Thừa kế từ DependencyObject và triển khai Delta dưới dạng DependencyProperty.

Tùy chọn đơn giản nhất là # 1. Bạn có thể thực hiện các giao diện INotifyPropertyChanged trên lớp của bạn khá dễ dàng:

public class YourClass : INotifyPropertyChanged 
{ 

    private int _delta; 
    public int Delta 
    { 
     get { return _delta; } 
     set { _delta = value; NotifyPropertyChanged("Delta"); } 
    } 

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

Bạn có thể đọc thêm về using and implementing dependency properties trên MSDN.

+3

+1 Hoàn toàn chính xác, nhưng đối với bất kỳ ai mới tham gia WPF, tôi khuyến khích bạn kiểm tra các câu trả lời khác, khi áp dụng bộ công cụ hiện có sẽ yêu cầu ít công việc hơn và giúp việc học dễ dàng hơn nhiều. – jeremyalan

+0

tôi có thể bỏ qua 'private int _delta;' bằng cách nào đó? Tôi muốn tính năng này được tạo tự động bởi C#, như thuộc tính bình thường – javapowered

+1

@javapowered: Thật không may, không. Bạn không thể có thuộc tính tự động "được triển khai một phần". Và nếu bạn cần gọi các phương thức trong setter (như trong trường hợp này), bạn phải cung cấp cả hai trường sao lưu và thực hiện thuộc tính. – LBushkin

3

Chỉ cần triển khai Giao diện INotifyPropertyChanged trong lớp của bạn và sử dụng nó để nâng cao PropertyChanged cho Thuộc tính của bạn và sau đó giao diện người dùng sẽ cập nhật. Nếu bạn đang sử dụng một mẫu dự án MVVM thì có một cơ hội tốt mà bạn đã có một phương thức trợ giúp được thực hiện, bạn chỉ cần sử dụng nó.

MSDN INotifyPropertyChanged

GalaSoft MVVM Light Toolkit

2

Các ObservableCollection tăng các sự kiện tự động nhưng đối với tài sản riêng của bạn, bạn phải tăng các biến cố chính mình.

Một ví dụ điển hình là ở đây: http://www.codeproject.com/Tips/228352/Naming-Properties-in-MVVM?display=Print

tôi muốn đề nghị sử dụng ánh sáng MVVM: http://mvvmlight.codeplex.com, tôi đã sử dụng nó trong Silverlight và các ứng dụng WPF. Rất dễ sử dụng và cung cấp một hệ thống nhắn tin giữa model, view model và view.

+1

Chỉ cần một lời nhắc nhở, rằng ngay cả trên một ObservableCollection bạn cần phải tăng tài sản thay đổi trong trường hợp tham chiếu đến bộ sưu tập chính nó thay đổi. –

2

Sử dụng @ trả lời LBushKin của, tôi sửa đổi nó để

public class Prop<T> : INotifyPropertyChanged 
{ 
    private T _value; 
    public T Value 
    { 
     get { return _value; } 
     set { _value = value; NotifyPropertyChanged("Value"); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    internal void NotifyPropertyChanged(String propertyName) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

và thiết lập nó:

class MainWindow ... 
    // a bool with initial value of true 
    public static Prop<bool> optionBool { get; set; } = new Prop<bool>{ Value = true }; 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     // connect 
     DataContext = this; 
    } 

và sử dụng nó:

<Grid ... 
    <CheckBox Content="Da Check" ... IsChecked="{Binding optionBool.Value}"/> 
0

Trong khi chúng tôi đang ở nó với việc cải thiện câu trả lời, một số bổ sung mới khác của C# 6.0 và 7.0 giúp làm cho gọn nhẹ hơn:

public class Prop<T> : INotifyPropertyChanged 
{ 
    private T _value; 

    public T Value 
    { 
     get => _value; 
     set { _value = value; NotifyPropertyChanged(nameof(_value)); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    internal void NotifyPropertyChanged(String propertyName) => 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
} 

Bằng cách này, bạn không sử dụng bất kỳ "giá trị được nhúng" nào (nghĩa là tên của tài sản) và giữ mã an toàn cho máy tái cấu trúc.

Và cũng không cần khối mã dự phòng do C# 6.0 và các tính năng mới của Biểu thức mới 7.0 của

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