我创建了一个自定义控件MyTextBox
,它继承自TextBox
. 它有一个与之关联的样式,其中包含一个命名控件:
<Style x:Key="{x:Type MyTextBox}" TargetType="{x:Type MyTextBox}">
<!-- ... -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MyTextBox}">
<!-- ... -->
<SomeControl x:Name="PART_SomeControl" />
<!-- ... -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
MyTextBox
有一个依赖属性,当设置时,将其值传播到SomeControl
:
public class MyTextBox : TextBox
{
// ...
public static new readonly DependencyProperty MyParameterProperty =
DependencyProperty.Register(
"MyParameter",
typeof(object),
typeof(MyTextBox),
new PropertyMetadata(default(object), MyParameterChanged));
private static void MyParameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var me = (MyTextBox)d;
var someControl = (SomeControl)me.GetTemplateChild("PART_SomeControl");
someControl.SetValue(SomeControl.MyParameterProperty, e.NewValue);
}
}
这在进行简单绑定时可以正常工作,如下所示:
<MyTextBox MyParameter="{Binding}" />
但是当我使用RelativeSource使用更花哨的绑定时,如下所示:
<MyTextBox MyParameter="{Binding DataContext, RelativeSource={RelativeSource
FindAncestor, AncestorType=ParentView}}"
该方法me.GetTemplateChild()
返回null
。也就是SomeControl
找不到。
为什么?
我所做的一个观察是,当它具有 时RelativeSource
,MyParameter
首先设置依赖属性。也就是说,如果我这样做:
<MyTextBox
OtherParameter="{Binding}"
MyParameter="{Binding DataContext, RelativeSource={RelativeSource
FindAncestor, AncestorType=ParentView}}"
该MyParameter
属性(奇怪地)设置在之前OtherParameter
。使用简单绑定,它们按照声明的顺序设置,正如预期的那样。
(如您所见,我的代码已从不相关的内容中删除。希望我已经包含了所有重要的内容。)