9

我正在创建一个具有 PropertyChangedCallback 依赖项属性的 WPF CustomControl。在该回调方法中,我尝试在使用 GetTemplateChild() 方法从 OnApplyMethod 检索的控件的某些部分上设置值。

问题是 PropertyChangedCallback (在某些系统上)在 OnApplyTemplate 之前调用,因此控制部分仍然为空。

我目前使用的解决方法是将 PropertyChangedCallback 中的 e.NewValue 保存到成员变量中,然后在 OnApplyTemplate() 中调用 SetValue(dp, _savedValue)。

处理这个问题的正确方法是什么,或者我是否已经在使用最好的解决方案?

4

1 回答 1

8

这就是我们所做的 - 原则上并没有解决问题,但提供了解决问题的明确方法。

  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 中检查您的 Part(s) 是否不为空(很可能是),如果是,则将 DeferredAction(OnValueChanged() 的新实例添加到上一步创建的列表中。注意,OnValueChanged() 是双重目的handler 它可以直接从您的 DP 值更改的处理程序中调用,如果 Parts 不为空,或者它被用作可执行的延迟操作。

  3. 在您的 OnApplyTemplate 中循环通过您的延迟操作列表(您知道,如果它们在那里,它们还没有被应用)并为它们中的每一个调用 Execute。清除最后的列表。

干杯

于 2011-01-21T09:21:48.337 回答