gpt4 book ai didi

c# - 当依赖属性具有 RelativeSource 绑定(bind)时,GetTemplateChild 返回 null

转载 作者:太空宇宙 更新时间:2023-11-03 20:05:22 31 4
gpt4 key购买 nike

我创建了一个自定义控件 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);
}
}

这在进行简单绑定(bind)时效果很好,如下所示:

<MyTextBox MyParameter="{Binding}" />

但是当我使用 RelativeSource 来使用更花哨的绑定(bind)时,就像这样:

<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 之前。使用简单绑定(bind),它们的设置顺序与声明的顺序相同,正如预期的那样。

(如您所见,我的代码已从不相关的内容中删除。希望我已包含所有重要内容。)

最佳答案

它很可能是在应用模板之前设置的。有几种方法可以解决这个问题:

  • 调用ApplyTemplateGetTemplateChild 之前强制加载模板。

  • 使用 BeginInvoke使用 DispatcherPriority.Loaded 延迟操作。

  • 如果没有模板,允许MyParameterChanged失败,重复OnApplyTemplate中的逻辑(无论如何你都应该这样做,以防模板在加载后被替换(如在 Windows 主题更改中)。

看起来您只是将值传递给子元素。您是否考虑过使用具有值继承的附加属性?

至于为什么 RelativeSource FindAncestor 绑定(bind)失败,而不是原始 DataContext 绑定(bind),我认为这归结为 DataContext 本身是一个继承属性.假设,假设操作顺序是这样的:

  1. 父级接收 DataContext 属性
  2. parent 加 child
  3. child 评价我的参数
  4. child 应用模板
  5. 子级从父级继承 DataContext

在第一种情况下,(MyParameter="{Binding}"),第 3 步无法更新 MyParameter,因为它还没有要绑定(bind)的 DataContext , 所以 MyParameterChanged 没有被调用并且没有异常。在第 5 步之后,当子项的 DataContext 更新时,它会重新计算 MyParameter,此时模板已经存在,因此属性更改处理程序可以工作。

在第二种情况下,您专门查找父级的 DataContext 属性,该属性确实存在,因此 MyParameterChanged 被调用于第 3 步失败,因为模板尚未应用。

关于c# - 当依赖属性具有 RelativeSource 绑定(bind)时,GetTemplateChild 返回 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23891424/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com