【问题标题】:DependencyProperty doesn't fire ValueChanged when new value is the same当新值相同时,DependencyProperty 不会触发 ValueChanged
【发布时间】:2011-10-13 04:54:29
【问题描述】:

好的,问题来了:我写了一个 UserControl,它接收一个新值,比如每 100 毫秒,然后用它做一些事情。它必须处理每个新的值设置器,即使值没有改变。 UserControl 有一些 DependencyProperties:

public double CurrentValue
    {
        get { return (double)GetValue(CurrentValueProperty); }
        set { SetValue(CurrentValueProperty, value); }
    }

    public static readonly DependencyProperty CurrentValueProperty =
       DependencyProperty.Register("CurrentValue", typeof(double), typeof(GraphControl), new UIPropertyMetadata(0d));

在使用此控件的 XAML 中,我只是将 CurrentValue 的 Binding 设置为(启用 INotifyPropertyChanged)属性:

<uc:UserControl CurrentValue="{Binding MyValue}" ... />

视图模型:

    public double MyValue
    {
        get { return _value; }
        set
        {
            //if (_value == value) return;
            _value= value;
            if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("MyValue"));
        }
    }

如您所见,我明确注释掉了 if equals then return,因此即使值更新为相同的值,它也会触发 PropertyChanged 事件。

现在回到我的用户控件,我尝试以两种方式注册 ValueChanged;首先使用DependencyPropertyDescriptor:

var propertyDescriptor = DependencyPropertyDescriptor.FromProperty(CurrentValueProperty, typeof(GraphControl));
propertyDescriptor.AddValueChanged(this, OnCurrentValueChanged);

或使用UIPropertyMetaData:

new UIPropertyMetadata(0d, OnCurrentValueChangedCallback)

所以回调的存根看起来像:

private void Callback(object sender, EventArgs e){
    //do stuff
}

好的,现在的问题是,当值没有显式更改时,不会触发回调。我检查了一下,PropertyChanged 事件在我的视图模型中触发,但控件没有看到变化。当值更改为新值时,它将按预期处理回调。
有什么方法可以覆盖这种行为,以便我的回调方法总是会被命中?

编辑:
我也尝试使用CoerceValueCallback,当值保持不变时,它会被击中,但我认为它对我的问题没有帮助......

【问题讨论】:

    标签: wpf callback dependency-properties inotifypropertychanged


    【解决方案1】:

    您可以将您的值包装在一个对象中,即创建一个类来保存它 - 然后每次都将属性设置为该类的包含新值的新实例。这意味着您每秒创建约 10 个对象,但它们各不相同,会触发更改事件,而且很小(无论如何都会被 GC)。 :)

    【讨论】:

    • 啊,当然了,这么简单的事情,我怎么没想到呢! :-) 效果很好,谢谢!
    【解决方案2】:

    另一种选择是将值暂时切换为其他值,然后恢复之前的值。您可以在 Coerce 回调中透明地完成整个技巧:

    public static readonly DependencyProperty TestProperty = DependencyProperty.Register(
        "Test", typeof(object), typeof(School),
        new PropertyMetadata(null, TestChangedCallback, TestCoerceCallback));
    
    static object TestCoerceCallback(DependencyObject d, object baseValue)
    {
        if (baseValue != null && (d.GetValue(TestProperty) == baseValue))
        {
            d.SetCurrentValue(TestProperty, null);
            d.SetCurrentValue(TestProperty, baseValue);
        }
        return baseValue;
    }
    

    只需确保您的属性代码可以优雅地处理 null 值大小写。

    【讨论】:

      猜你喜欢
      • 2012-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-21
      • 2020-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多