如何在wpf ViewModel中实现observable int?

jav*_*red 18 c# wpf mvvm

在我的mvvm ViewModel中,我有这样的字段

public int Delta { get; private set; }
Run Code Online (Sandbox Code Playgroud)

但是当我更新它时:

Delta = newValue;
Run Code Online (Sandbox Code Playgroud)

用户界面未刷新.

我以为数据绑定会为我做这件事.例如,我可以将集合声明为ObservableCollection,然后数据绑定将起作用.

但是没有ObservableInt,怎么说查看它需要刷新呢?

可能我应该提出一些事件"通知财产改变"或什么?

LBu*_*kin 34

你有两个选择:

  1. INotifyPropertyChanged在您的类上实现接口.
  2. 继承自DependencyObject并将Delta实现为DependencyProperty.

最简单的选择是#1.您可以非常轻松地在类上实现INotifyPropertyChanged接口:

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));
      }
  }
  }
Run Code Online (Sandbox Code Playgroud)

您可以阅读有关在MSDN上使用和实现依赖项属性的更多信息.

  • +1绝对正确,但对于WPF的新手,我鼓励您查看其他答案,因为采用现有工具包将需要更少的工作并使学习框架更容易. (3认同)

Ban*_*cid 6

使用@LBushKin的答案,我将其修改为

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

并进行设置:

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 UI to be able to use the Prop
        DataContext = this;
    }
Run Code Online (Sandbox Code Playgroud)

并使用它:

<Grid ...
    <CheckBox Content="Da Check" ... IsChecked="{Binding optionBool.Value}"/>
Run Code Online (Sandbox Code Playgroud)

这里还有一个 Collection 和 2-Properties 版本: Utils.ObservableProperties.cs(此存储库包含几个相关的类)


小智 5

虽然我们正在改进答案,但 c# 6.0 和 7.0 的其他一些新增功能有助于使其更加紧凑:

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));
}
Run Code Online (Sandbox Code Playgroud)

这样,您就不会使用任何“嵌入值”(即 - 属性的名称)并保持代码重构安全。

由于 c# 6.0 和 7.0 的新 Expression body 特性,也不需要多余的代码块

  • 这不应该是 ```nameof(value)``` 而不是 ```nameof(_value)``` 吗?并且可以通过使用 ```NotifyPropertyChanged()``` 方法声明上的 ```CallerMemberName``` 属性来完全避免该参数。 (5认同)