0

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属性。我设置属性的原因是因为我想访问和子项来分别设置文本和数据绑定。基本上我只想访问的孩子。我怎样才能访问它们?StackPanelThumbx:KeyStackPanelTextBlockDataGridStackPanel

编辑:我已将其更改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>

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

tb.Template = ct

现在Thumb渲染了,但我仍然无法按照这里的建议访问内部控件。出于某种原因,tb.TemplateNothing我这样做时:

Dim txtBlock As TextBlock = CType(tb.Template.FindName("tplTextBlock", tb), TextBlock)
4

1 回答 1

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。

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


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

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

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

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

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

于 2012-08-12T13:59:48.813 回答