我在一个简单的问题追平自己在海里。 我有一个实现类INotifyPropertyChanged
。 一些实例属性干将使用静态特性,因此它们的值可以,如果静态属性的改变而改变? 这里有一个简单的例子。
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弱事件处理程序-第一部分
在一个不相关的音符你的代码是目前射击属性改变的时候,其实属性值并没有改变。 例如:
- 设置MinimumLength至5;
- 设定长度至10; (由于从缺省0-5的值变化事件触发)
- 设定长度11; (事件触发,但它不应该由于长度仍然5)
您可以使用中提到的技术结合静态属性和实现INotifyPropertyChanged的 ,但也提出了一个通知对“长度”,例如,
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像
<StackPanel>
<StackPanel.Resources>
<screenControls:ZoomVm x:Key="ZoomVm" />
</StackPanel.Resources>
<TextBlock Text="{Binding ElementName=uiScaleSliderContainer, Path=Tag}" Foreground="White" Margin="0,0,20,0" />
<Control Name="uiScaleSliderContainer"
Margin="0,0,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Tag="{Binding Source={StaticResource ZoomVm}, Path=Instance.ZoomLevel}">
<Control.Template>
<ControlTemplate>
<Slider Orientation="Horizontal"
Width="400"
x:Name="uiScaleSlider"
ToolTip="Zoom"
Value="{Binding ElementName=uiScaleSliderContainer, Path=Tag}"
Minimum="0.1"
Maximum="2"
TickFrequency="0.1"
IsSnapToTickEnabled="True">
</Slider>
</ControlTemplate>
</Control.Template>
</Control>
</StackPanel>