WPF CustomControl:在 PropertyChangedCallback 之后调用 OnApplyTemplate
我正在创建一个 WPF CustomControl,它具有 PropertyChangedCallback 的依赖属性。在该回调方法中,我尝试设置使用 GetTemplateChild() 方法从 OnApplyMethod 检索的某些控件部分的值。
问题是 PropertyChangedCallback (在某些系统上)在 OnApplyTemplate 之前调用,因此控件部分仍然为空。
我当前使用的解决方法是将 e.NewValue 从 PropertyChangedCallback 保存到成员变量,然后在 OnApplyTemplate() 中调用 SetValue(dp, _savedValue)。
处理这个问题的正确方法是什么,或者我是否已经使用了最好的解决方案?
I am creating a WPF CustomControl that has a dependency property with PropertyChangedCallback. In that Callback method I try to set values on some of the control's parts that I retrieve from OnApplyMethod using the GetTemplateChild() method.
The problem is that the PropertyChangedCallback is (on some systems) called before OnApplyTemplate so the control parts are still null.
The workaround I'm currently using is to save e.NewValue from the PropertyChangedCallback to a member variable and then call SetValue(dp, _savedValue) in OnApplyTemplate().
What is the proper way to deal with this problem or am I already using the best solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这就是我们所做的——不从原则上解决问题,而是提供一种明确的解决方法。
为 DP 值更改事件创建一个处理程序,设为 OnValueChanged()。一般不需要参数,因为您知道哪个 DP 发生了更改并且始终可以获得其当前值。
使用构造函数创建一个名为 DeferredAction 的类/结构,接受 System.Action (这将是对 OnValueChanged() 的引用)。该类将有一个属性 Action 和一个名为 Execute() 的方法。
这是我使用的:
在您的控件中创建一个列表。该集合将保留 DeferredAction 的列表,直到它们可以成功应用(通常在 base.OnApplyTemplate() 之后)。应用操作后,必须清除集合以避免重复处理。
在 OnValueChanged 中检查您的 Part(s) 是否不为空(很可能为空),如果是,则将 DeferredAction(OnValueChanged() 的新实例添加到上一步创建的列表中。注意,OnValueChanged() 是一个双重用途处理程序,可以直接从您的 DP 值更改处理程序中调用它,如果 Parts 不为 null,或者将其用作可执行的延迟操作。
在您的 OnApplyTemplate 中循环遍历您的延迟操作列表(您知道,如果它们在那里,则它们尚未应用)并为每个部件调用 Execute。最后清除列表。
干杯
that's what we do - doesn't solve the problme in priciple but provides with a clear way to fix it.
Create a handler for the DP value changed event, let it be OnValueChanged().Generally no paramters needed as you know which DP is changed and can always obtain its current value.
Create a class/struct called DeferredAction with the constructor, accepting System.Action (that's going to be a ref to your OnValueChanged()). The class will have a property Action and a method, called Execute().
Here's what I use:
In your control create a List. The collection will keep the list of DeferredAction's until they can be successfully applied (typically after base.OnApplyTemplate()). Once actions are applied the collection has to be cleared to avoid double processing.
Within OnValueChanged do check if your Part(s) is not null (which it likely is) and if so add a new instance of DeferredAction(OnValueChanged() to the list created at a previous step. Note, OnValueChanged() is a dual purpose handler it can be called right from your DP value changed handler, if Parts aren't null, alterantively it's used as an executable deferred action.
Within you OnApplyTemplate loop through your deferred actions list (you know, if they're there, they haven't been applied) and call Execute for each of them. Clear the list at the end.
Cheers