INotifyPropertyChanged and static properties

依然范特西╮ 提交于 2019-11-30 11:12:28

If you're inclined to maintain that design then I would go with a solution like the following:

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;
    }
}

This is pretty much equivalent to maintaining a list of instances but I find it more maintainable and clearer. Also, you really need to use a weak event handler strategy, otherwise, your instances will not be garbage collected because they will always be associated with the static event which acts like a GC root.

You can read more about weak event handlers in the following blog posts (which were written by me so I'm biased):

.NET Weak Event Handlers – Part I

.NET Weak Event Handlers – Part I

In an unrelated note your code is currently firing property changed when in fact the property value did not change. For example:

  1. Set MinimumLength to 5;
  2. Set length to 10; (event fires since the value changes from the default 0 to 5)
  3. Set length to 11; (event fires but it should not since the length is still 5)
Phil

You could use the technique mentioned in Binding static property and implementing INotifyPropertyChanged but also raise a notification against "length", e.g.

class ExampleClass : INotifyPropertyChanged
{
    private static int _MinimumLength = 5;

    public int MinimumLength
    {
        get
        {
            return _MinimumLength;
        }
        set
        {
            if (_MinimumLength != value)
            {
                _MinimumLength = value;

                OnPropertyChanged("MinimumLength");
                OnPropertyChanged("length");
            }
        }
    }
    ...
}

i was faced to the same problem. Here is the solution i have put in place.

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; }
    }
}

Then i use it in the XAML like that

<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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!