INotifyPropertyChanged和静态属性

我想把自己绑在一个简单的问题上。 我有一个实现INotifyPropertyChanged的类。 某些实例属性的getter使用静态属性,因此如果静态属性发生变化,它们的值可能会发生变化? 这是一个简化的例子。

 class ExampleClass : INotifyPropertyChanged { private static int _MinimumLength = 5; public static int MinimumLength { get { return _MinimumLength; } set { if (_MinimumLength != value) { _MinimumLength = value; //WHAT GOES HERE } } } private int _length = -1; public int length { get { return (_length > _MinimumLength) ? _length : _MinimumLength; } set { var oldValue = (_length > _MinimumLength) ? _length : _MinimumLength; if (_length != value) { _length = value; var newValue = (_length > _MinimumLength) ? _length : _MinimumLength; if (newValue != oldValue) { OnPropertyChanged("length"); } } } } public event PropertyChangedEventHandler PropertyChanged; [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } 

显然,如果静态属性MinimumLength发生更改,则每个实例的属性length也可能会更改。 但是静态属性应该如何表示对实例的可能更改? 它不能调用OnPropertyChanged因为它不是静态的。

我可以在所有实例的类级别保留一个列表,并在每个实例上调用一个方法,但不知怎的,这感觉就像是矫枉过正。 或者我可以将静态属性拉出到单例类中,但逻辑上它们仍然存在于类级别。 是否有既定的模式,或者我应该以不同的方式考虑这个问题?

如果您倾向于维护该设计,那么我将使用如下解决方案:

 public static int MinimumLength { get { return _MinimumLength; } set { if (_MinimumLength != value) { _MinimumLength = value; OnGlobalPropertyChanged("MinimumLength"); } } } static event PropertyChangedEventHandler GlobalPropertyChanged = delegate { }; static void OnGlobalPropertyChanged(string propertyName) { GlobalPropertyChanged( typeof (ExampleClass), new PropertyChangedEventArgs(propertyName)); } public ExampleClass() { // This should use a weak event handler instead of normal handler GlobalPropertyChanged += this.HandleGlobalPropertyChanged; } void HandleGlobalPropertyChanged(object sender, PropertyChangedEventArgs e) { switch (e.PropertyName) { case "MinimumLength": if (length > MinimumLength) length = MinimumLength; break; } } 

这几乎等同于维护实例列表,但我发现它更易于维护和清晰。 此外,您确实需要使用弱事件处理程序策略,否则,您的实例将不会被垃圾收集,因为它们将始终与静态事件相关联,静态事件的行为类似于GC根。

您可以在以下博客文章中阅读有关弱事件处理程序的更多信息(由我编写,因此我有偏见):

.NET弱事件处理程序 – 第一部分

.NET弱事件处理程序 – 第一部分

在一个不相关的注释中,您的代码当前触发属性已更改,而实际上属性值未更改。 例如:

  1. 将MinimumLength设置为5;
  2. 设定长度为10; (事件触发,因为值从默认值0更改为5)
  3. 设定长度为11; (事件发生但不应该因为长度仍为5)

您可以使用Binding静态属性中提到的技术并实现INotifyPropertyChanged,但也可以针对“length”发出通知,例如

 class ExampleClass : INotifyPropertyChanged { private static int _MinimumLength = 5; public int MinimumLength { get { return _MinimumLength; } set { if (_MinimumLength != value) { _MinimumLength = value; OnPropertyChanged("MinimumLength"); OnPropertyChanged("length"); } } } ... } 

我遇到了同样的问题。 这是我已经实施的解决方案。

 public class ZoomDataVm : ModelBase { public ZoomDataVm() { // initialise the zoom } private double _zoomLevel; public double ZoomLevel { get { return _zoomLevel; } set { if (_zoomLevel != value) { _zoomLevel = value; RaisePropertyChanged(() => ZoomLevel); // // persist zoom info } } } } public class ZoomVm : ModelBase { public static ZoomDataVm _instance; static ZoomVm() { _instance = new ZoomDataVm(); } public ZoomDataVm Instance { get { return _instance; } } } 

然后我就像那样在XAML中使用它