问题
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?
回答1:
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:
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();
}
}
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
来源:https://stackoverflow.com/questions/1298898/wpf-customcontrol-onapplytemplate-called-after-propertychangedcallback