DependencyProperty не запускает ValueChanged, когда новое значение совпадает - PullRequest
14 голосов
/ 26 июля 2011

Хорошо, вот в чем проблема: я написал 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-enabled):

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

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

Ответы [ 2 ]

5 голосов
/ 26 июля 2011

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

0 голосов
/ 22 января 2017

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...