当新值相同时,DependencyProperty不会触发ValueChanged

时间:2011-07-26 07:53:02

标签: wpf callback dependency-properties inotifypropertychanged

好的,这就是问题所在:我编写了一个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事件在我的viewmodel中触发,但控件没有看到更改。当值更改为新值时,它将按预期处理回调 有没有办法覆盖这种行为,以便我的回调方法总是被击中?

修改
我也尝试使用CoerceValueCallback,并且当值保持不变时,它会被击中,但是我认为这对我的问题没有帮助...

2 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:0)

另一种方法是暂时将值切换为其他值,然后恢复前一个值。您可以在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值。