WPF自定义控件:在PropertyChangedCallback之后调用OnApplyTemplate

10
我正在创建一个具有PropertyChangedCallback依赖属性的WPF CustomControl。在该回调方法中,我尝试使用GetTemplateChild()方法从OnApplyMethod检索一些控件部件,并在这些部件上设置值。
问题在于,在某些系统上,PropertyChangedCallback在OnApplyTemplate之前被调用,因此控件部件仍为空。
我目前使用的解决方法是将PropertyChangedCallback中的e.NewValue保存到成员变量中,然后在OnApplyTemplate()中调用SetValue(dp, _savedValue)。
如何正确地处理此问题或者我已经使用了最佳解决方案?

2
不知道为什么还没有人回答你的问题,但我可以说,我基本上和你做的一样,到目前为止似乎通常都是有效的。最近我遇到了一个特定的问题,在 SplitButton 实现中做了这个,第一个选定的项目不会显示出来,但手动选择项目后就可以了。 - jpierson
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中检查你的部件是否为null(通常是这样),如果是,则添加一个以前步骤中创建的DeferredAction(OnValueChanged())的新实例到列表中。请注意,OnValueChanged()是双重目的处理程序,如果部件不为null,它可以直接从DP值更改处理程序调用,或者作为可执行的延迟操作使用。

  3. 在你的OnApplyTemplate中循环遍历你的延迟操作列表(如果它们存在,则它们尚未应用)并为每个操作调用Execute。在结束时清除列表。

干杯!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接