WPF CustomControl: OnApplyTemplate вызывается после PropertyChangedCallback

Я создаю WPF CustomControl со свойством зависимости с PropertyChangedCallback. В этом методе обратного вызова я пытаюсь установить значения для некоторых частей элемента управления, которые я извлекаю из OnApplyMethod, используя метод GetTemplateChild().

Проблема в том, что PropertyChangedCallback (в некоторых системах) вызывается перед OnApplyTemplate, поэтому части управления по-прежнему пусты.

В настоящее время я использую обходной путь, чтобы сохранить e.NewValue из PropertyChangedCallback в переменную-член, а затем вызвать SetValue(dp, _savedValue) в OnApplyTemplate().

Каков правильный способ решения этой проблемы, или я уже использую лучшее решение?


person Community    schedule 19.08.2009    source источник
comment
Не уверен, почему никто еще не ответил на ваш вопрос, но я могу сказать, что я делаю то же самое, что и вы, и пока это в целом работает. Недавно я столкнулся с определенной проблемой в реализации SplitButton, которая делает это, когда первый выбранный элемент не отображается, но после ручного выбора элемента он появляется.   -  person jpierson    schedule 07.05.2010


Ответы (1)


это то, что мы делаем - не решает проблему в принципе, но предоставляет четкий способ ее решения.

  1. Создайте обработчик для события изменения значения DP, пусть это будет OnValueChanged(). Как правило, параметры не нужны, так как вы знаете, какой DP изменен, и всегда можете получить его текущее значение.

  2. Создайте класс/структуру с именем DeferredAction с конструктором, принимая System.Action (это будет ссылка на ваш OnValueChanged()). Класс будет иметь свойство Action и метод Execute().

Вот что я использую:

class DeferredAction
{
   private Action action;

    public DeferredAction(Action action)
    {
        this.action = action;
    }

    private Action Action
    {
        get { return this.action; }
    }

    public void Execute()
    {
        this.Action.Invoke();
    }
}
  1. В вашем контроле создайте список. Коллекция будет хранить список DeferredAction до тех пор, пока они не будут успешно применены (обычно после base.OnApplyTemplate()). После применения действий коллекция должна быть очищена, чтобы избежать двойной обработки.

  2. Внутри OnValueChanged проверьте, не является ли ваша Часть(и) нулевой (что, скорее всего, так и есть), и если да, добавьте новый экземпляр DeferredAction(OnValueChanged() в список, созданный на предыдущем шаге. Обратите внимание, OnValueChanged() имеет двойное назначение. обработчик его можно вызвать прямо из обработчика изменения значения DP, если части не равны нулю, альтернативно он используется как исполняемое отложенное действие.

  3. В вашем цикле OnApplyTemplate список отложенных действий (вы знаете, если они там есть, они не были применены) и вызовите Execute для каждого из них. Очистите список в конце.

Ваше здоровье

person Community    schedule 21.01.2011