DependencyProperty не запускает ValueChanged, когда новое значение одинаково

Итак, вот проблема: я написал 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, где этот элемент управления используется, я просто устанавливаю Binding CurrentValue в свойство (INotifyPropertyChanged):

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

ViewModel:

    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, но элемент управления не видит изменения. Когда значение изменится на новое значение, оно обработает обратный вызов, как ожидалось.
Есть ли способ переопределить это поведение, чтобы мой метод обратного вызова всегда попадался?

EDIT:
Я также попытался использовать CoerceValueCallback, и тот попадает, когда значение остается неизменным, но это не помогает мне с моей проблемой, я думаю...

Ответы

Ответ 1

Вы можете обернуть свое значение в объекте, т.е. создать класс для его хранения, а затем каждый раз присваивать свойству новый экземпляр этого класса, содержащий новое значение. Это означает, что вы создаете ~ 10 объектов в секунду, но они разные, вызовут событие изменения и будут только небольшими (будет GC'd в любом случае).:)

Ответ 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.