访问ControlTemplate中的控件

这是xaml:

            

我想要访问名为textBlock2的TextBlock。
我试图覆盖OnApplyTemplate但是得到了null。

我试过了:

 Grid gridInTemplate = (Grid)btnWedding.Template.FindName("grid", btnWedding); var ct0 = btnWedding.Template.FindName("textBlock2", btnWedding); var ct1 = btnWedding.FindName("textBlock2"); var ct2 = btnWedding.FindResource("textBlock2"); 

gridInTemplate为null(从MSDN获取的样本)。
当然,ct#都是null。

我在这里想念的是什么?

如果您已重写OnApplyTemplate,则不要使用FindResource()或Template.FindName()或任何使用VisualTreeHelper的黑客攻击。 只需使用this.GetTemplateChild("textBlock2");

WPF中的模板具有自包含的名称范围。 这是因为模板被重用,并且当控件的多个实例每个实例化其模板时,模板中定义的任何名称都不能保持唯一。 调用GetTemplateChild方法以在实例化后返回对来自模板的对象的引用。 您不能使用FrameworkElement.FindName方法从模板中查找项目,因为FrameworkElement.FindName在更一般的范围内运行,并且一旦应用了ControlTemplate类本身和实例化模板之间就没有连接。

检查此链接:

http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.gettemplatechild.aspx

如果您的示例是microsoft示例,那么我建议您再次阅读它。 你可能已经跳过了一些东西。

http://msdn.microsoft.com/en-us/library/bb613586.aspx

总结一下 – 在创作自定义控件时使用GetTemplateChild(),例如OnApplyTemplate,在其他情况下使用Template.FindName。

您的代码是正确的,但可能不在正确的位置… FindName仅在应用模板后才有效。 通常,在自定义控件中重写OnApplyTemplate时使用它。 由于您没有创建自定义控件,因此可以在按钮的Loaded事件中执行此操作。

请尝试以下代码。 这将返回模板化元素。

 this.GetTemplateChild("ControlName"); 

您可以使用VisualTreeHelper迭代按钮的可视树以获取任何子项。 您可以使用此基本通用函数来获取它

 private static DependencyObject RecursiveVisualChildFinder(DependencyObject rootObject) { var child = VisualTreeHelper.GetChild(rootObject, 0); if (child == null) return null; return child.GetType() == typeof (T) ? child : RecursiveVisualChildFinder(child); } 

你可以像使用它一样

 TextBlock textblock = RecursiveVisualChildFinder(btnWedding); if(textblock.Name == "textBlock2") {// Do your stuff here } 

如果你可以获得网格控制,那么尝试使用下面的代码

 TextBlock textBlock2 = (TextBlock)gridInTemplate.Children[1]; 

方法“FrameworkElement.FindName(string name)”使用布局的名称范围,其中使用按钮/控件来解析名称。 简而言之,您可以使用它在应用程序布局中的网格或堆栈面板中查找子项。 但是你不能使用它来查找你在应用程序布局中使用的控件的子项(因为模板化的chidren名称在不同的范围内)

让你的孩子在你的情况下的一种方法是inheritance按钮。 由于您不会修改按钮的任何其他属性或行为,因此新按钮将正常工作。 实际上我从来没有使用这种方法来访问模板化的孩子,因为我从来没有必要在控件类的范围之外使用它们。

 public class WeddingButton : Button { public override void OnApplyTemplate() { TextBlock textBlock = this.GetTemplateChild("textBlock2") as TextBlock; base.OnApplyTemplate(); } }