在我的 MVVM ViewModel 中,我有这样的字段
public int Delta { get; private set; }
但是当我像这样更新它:
Delta = newValue;
UI没有刷新。
我曾认为数据绑定会自动刷新UI。例如,我可以将集合声明为ObservableCollection
,然后数据绑定就会生效。
但是,没有ObservableInt
这样的东西,那么该如何告诉View需要进行刷新呢?
也许我应该触发某个事件“通知属性已更改”之类的东西吗?
在我的 MVVM ViewModel 中,我有这样的字段
public int Delta { get; private set; }
但是当我像这样更新它:
Delta = newValue;
UI没有刷新。
我曾认为数据绑定会自动刷新UI。例如,我可以将集合声明为ObservableCollection
,然后数据绑定就会生效。
但是,没有ObservableInt
这样的东西,那么该如何告诉View需要进行刷新呢?
也许我应该触发某个事件“通知属性已更改”之类的东西吗?
你有两个选择:
INotifyPropertyChanged
接口。最简单的选项是#1。你可以很容易地在你的类上实现INotifyPropertyChanged接口:
public class YourClass : INotifyPropertyChanged
{
private int _delta;
public int Delta
{
get { return _delta; }
set { _delta = value; PropertyChanged?.Invoke(nameof(Delta)); }
}
public event PropertyChangedEventHandler PropertyChanged;
}
你可以在MSDN上阅读更多关于使用和实现依赖属性的内容。
顺便提一下,除了改进答案外,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));
}
nameof(value)
而不是nameof(_value)
吗?而且可以通过在NotifyPropertyChanged()
方法声明上使用CallerMemberName
属性来避免使用参数。" - UweBaemayrpublic 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));
}
}
并进行设置:
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;
}
并且要使用它:
<Grid ...
<CheckBox Content="Da Check" ... IsChecked="{Binding optionBool.Value}"/>
ObservableCollection
会自动触发事件,但对于您自己的属性,您需要自己触发事件。一个好的例子在这里:http://www.codeproject.com/Tips/228352/Naming-Properties-in-MVVM?display=Print。public class YourClass : INotifyPropertyChanged
{
private int _delta;
public int Delta
{
get { return _delta; }
set {
_delta = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged();
}
}
// Declare the event
public event PropertyChangedEventHandler PropertyChanged;
public YourClass()
{
}
// Create the OnPropertyChanged method to raise the event
// The calling member's name will be used as the parameter.
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
它利用CallerMemberName来跳过手动输入属性名称的步骤。更多详细信息请参阅MSDN文档