访问ControlTemplate中的控件

时间:2012-08-12 13:33:07

标签: .net wpf vb.net controltemplate

我在资源字典文件中定义了ControlTemplate

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 <ControlTemplate x:Key="ctlTemplate">
    <ControlTemplate.Resources>
        <StackPanel x:Key="sp" x:Name="sp">
                <TextBlock Name="tplTextBlock" HorizontalAlignment="Center"/>
                <DataGrid  Name="tableBlock" AutoGenerateColumns="False"/>
            </StackPanel>
    </ControlTemplate.Resources>
 </ControlTemplate>
</ResourceDictionary>

我有一个派生自Thumb的课程,我正在尝试将其Template属性设置为上述ControlTemplate

Dim ct As ControlTemplate = CType(Application.Current.Resources("ctlTemplate"), ControlTemplate)
Dim tb As MovableTableBlock = New MovableTableBlock 'Derives from Thumb
tb.Template = ct
tb.UpdateLayout()

问题是Thumb根本没有呈现。但是,如果我删除ControlTemplate.Resources标记,结果也会移除x:Key的{​​{1}}属性,则会呈现StackPanel。我设置Thumb的{​​{1}}属性的原因是因为我想访问x:KeyStackPanel子项以分别设置文本和数据绑定。基本上我只想访问TextBlock的孩子。我怎样才能访问它们?

编辑: 我已将DataGrid更改为:

StackPanel

所以现在,我不必像这样设置模板:

ControlTemplate

现在呈现<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:VQ.Custom"> <Style TargetType="{x:Type local:MovableTableBlock}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:MovableTableBlock}"> <StackPanel x:Name="sp"> <TextBlock x:Name="tplTextBlock" HorizontalAlignment="Center"/> <DataGrid x:Name="tableBlock" AutoGenerateColumns="False"/> </StackPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> 但我仍然无法按照建议here访问内部控件。出于某种原因,当我这样做时,tb.Template = ct Thumb

tb.Template

1 个答案:

答案 0 :(得分:0)

您可以使用隐式样式设置模板:

    <Application x:Class="WpfApplication1.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:local="clr-namespace:WpfCustomControlLibrary2;assembly=WpfCustomControlLibrary2"
                 StartupUri="MainWindow.xaml">
        <Application.Resources>
            <Style TargetType="local:MovableTableBlock">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="local:MovableTableBlock">
                            <StackPanel x:Name="sp">
                                <TextBlock Name="tplTextBlock" HorizontalAlignment="Center"/>
                                <DataGrid  Name="tableBlock" AutoGenerateColumns="False"/>
                            </StackPanel>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Application.Resources>
    </Application>

    // No need to set Template or Style on MovableTableBlock, as it's done implicitly
    MovableTableBlock mtb = new MovableTableBlock();
    mtb.UpdateLayout(); // pointless to do...as not in visual tree yet

    .....your mtb needs to be added to the visual tree e.g. add as child of
    Grid or other element, so the style and template can be applied....your
    OnApplyTemplate won't be called till then.

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        TextBlock tb = Template.FindName("tplTextBlock", this) as TextBlock;
    }

我已经尝试了上面的代码,并且可以使用上面的方法访问模板中的TextBlock。

您尝试更改模板的方式有点不同寻常......下面有一些关于如何组织自定义控件的建议。


当您编写自定义控件时,您希望某些命名元素出现在模板中,那么将它们命名为“parts”并使用自定义控件类上的[TemplatePart]属性是一种约定。这样,重新模板化控件的人就知道哪些部分对于重新设计的模板至关重要。

另外,您提到您正在访问TextBlock和DataGrid,以便您可以设置文本和DataBinding。

不要这样做,而是考虑在自定义控件上公开一些属性...然后您的模板会使用“{TemplateBinding ...}”或“{Binding ...RelativeSource={RelativeSource TemplatedParent} ...}”绑定到该属性。

此外,通过从资源中查找模板并在代码后面设置模板,将模板设置到自定义控件中的方式非常规......您应该通过默认样式选择它。

以下是一些有助于解释的链接: