如何以编程方式访问ContentTemplate中定义的元素?

问题描述:

比方说,我已经创建XAML中定义的以下的ContentTemplate一个用户控件:如何以编程方式访问ContentTemplate中定义的元素?

<UserControl.ContentTemplate> 
    <DataTemplate> 
     <Ellipse Name="myEllipse" Stroke="White"/> 
     <ContentPresenter Content="{TemplateBinding Content}"/> 
    </DataTemplate> 
</UserControl.ContentTemplate> 

我将如何访问我的代码中的“myEllipse”元素,这样,例如,我能找到它与“高度myEllipse.Height“?我无法直接通过名称访问它。我试图创建一个参考:

Ellipse ellipse = ContentTemplate.FindName("myEllipse",this) as Ellipse; 

它运行程序时崩溃,说它不能创建我的类的实例。也许我没有正确使用FindName。如果任何人都可以帮助我,将不胜感激。

感谢,

达拉尔

为了使用FindName上一个DataTemplate,你需要将ContentPresenter参考。见Josh Smith的文章How to use FindName with a ContentControl

你实际上想要做的是使用ControlTemplate而不是DataTemplate。这应该更易于使用,并且会让您的控件的用户应用他们自己的内容模板或使用隐式模板。如果你做这样的事情:

<UserControl.Template> 
    <ControlTemplate TargetType="UserControl"> 
     <Grid> 
      <ContentPresenter/> 
      <Ellipse Name="myEllipse" Stroke="White"/> 
     </Grid> 
    </ControlTemplate> 
</UserControl.Template> 

然后在代码(也许在OnApplyTemplate重写),你就可以做到这一点:

var ellipse = Template.FindName("myEllipse", this) as Ellipse; 

你也应该用TemplatePartAttribute这样的装饰类:

[TemplatePart(Name="myEllipse", Type = typeof(Ellipse))] 

因此,如果有人重新模板您的控件,他们知道提供一个带有该名称的椭圆元素。 (如果该类仅在内部使用,则此类重要性较低)。

最后,如果您只想更改椭圆的颜色,那么您可能只是想使用数据绑定。你可以在你的控件上创建一个EllipseColor依赖属性,并设置Stroke="{TemplateBinding EllipseColor}"

+0

感谢您提供非常丰富的答案。我尝试使用ControlTemplate代替我的DataTemplate,但我的UserControl看起来不一样,并且某些功能受到了影响,所以我宁愿尝试使用DataTemplate来处理它,现在我已经了解了这一点我的控制发展。 在阅读Josh Smith的文章后,我试着在构造函数中为我的控件添加以下行: ContentPresenter contentPresenter = VisualTreeHelper.GetChild(this,0)as ContentPresenter; 不幸的是,它在该行失败。我得到一个XAML解析异常。有任何想法吗? – Dalal 2010-07-29 22:20:11

+1

@Dalal:构造函数中尚未填充可视化树,所以在GetChild调用中出现超出范围的异常。这被封装在一个XAML解析异常中,因为它没有实例化你的对象。您将需要将代码移到Load事件处理程序或OnApplyTemplate覆盖。另外,UserControl的默认控件模板在Border中有一个ContentPresenter,因此'VisualTreeHelper.GetChild(this,0)'将返回一个Border。你需要做一些像'VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this,0),0)'。 – Quartermeister 2010-07-30 02:40:40

+0

在我OnApplyTemplate重写我能顺利拿到ContentPresenter使用行'VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(此,0),0)作为ContentPresenter;'现在我不得不引用名为我的对象之一“ headerLabel',所以我把'headerLabel = ContentTemplate.FindName(“headerLabel”,contentPresenter)作为Label;'我得到一个InvalidOperationException:这个操作只对应用这个模板的元素有效。那么,教程说在ContentPresenter中传递。我做到了。我也试着把这段代码放在MouseDown事件中无济于事。 – Dalal 2010-07-30 18:08:58

尝试

<Ellipse Name="myEllipse" Stroke="{TemplateBinding Background}"/> 

,而不是编程方式改变它。

这里有一个类似的例子,用蓝色填充的椭圆。 http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter.aspx

+0

我的问题是获取对象的引用,而不是改变它的描边。我只是将中风用作示例,但由于它有点不清楚,我现在要编辑它。谢谢。 – Dalal 2010-07-29 21:25:24