WPF CustomControl:在PropertyChangedCallback之后调用的OnApplyTemplate

WPF CustomControl:在PropertyChangedCallback之后调用的OnApplyTemplate,wpf,propertychanged,custom-controls,Wpf,Propertychanged,Custom Controls,我正在创建一个WPF CustomControl,它有一个带有PropertyChangedCallback的依赖属性。在该回调方法中,我尝试在使用GetTemplateChild()方法从OnApplyMethod检索的控件的某些部分上设置值 问题是(在某些系统上)在应用程序模板之前调用PropertyChangedCallback,因此控制部分仍然为空 我当前使用的解决方法是将PropertyChangedCallback中的e.NewValue保存到成员变量,然后在OnApplyTempl

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

问题是(在某些系统上)在应用程序模板之前调用PropertyChangedCallback,因此控制部分仍然为空

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


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

这就是我们所做的-不解决原则上的问题,但提供了一个明确的解决方法

  • 为DP value changed事件创建一个处理程序,让它成为OnValueChanged()。通常不需要参数,因为您知道更改了哪个DP,并且始终可以获取其当前值

  • 使用构造函数创建一个名为DeferredAction的类/结构,接受System.Action(这将是对OnValueChanged()的引用)。该类将有一个属性操作和一个名为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();
        }
    }
    
  • 在控件中创建一个列表。集合将保留延迟操作的列表,直到它们可以成功应用为止(通常在base.OnApplyTemplate()之后)。应用操作后,必须清除集合以避免重复处理

  • 在OnValueChanged中,请检查您的部件是否为空(很可能是空的),如果是空的,请将DeferredAction的新实例(OnValueChanged()添加到上一步创建的列表中。注意,OnValueChanged()是一个双重用途的处理程序,它可以直接从DP值更改的处理程序调用,如果部分不为null,则交替地将其用作可执行的延迟操作

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


  • 干杯

    我不确定为什么还没有人回答你的问题,但我可以说,我正在做与你差不多的事情,到目前为止,这似乎是可行的。我最近在SplitButton实现中遇到了一个特殊问题,即第一个选中的项目不显示,但在手动选择一个项目后,它会显示出来做