繁体   English   中英

访问 ControlTemplate 内的控件

[英]Accessing a control inside a ControlTemplate

这是xaml:

<Page.Resources>
    <ControlTemplate x:Key="WeddingButtonBigTemplate" TargetType="Button">
        <Grid>
            <Image x:Name="imgNormal" Source="../Images/Married_button2.png"/>
            <TextBlock x:Name="textBlock2" Style="{StaticResource RegularBlueSpecialBoldText}" LineHeight="28" LineStackingStrategy="BlockLineHeight" HorizontalAlignment="Center" Margin="10,30,10,70" TextWrapping="Wrap" TextAlignment="Center" VerticalAlignment="Stretch" >
                <Run FontSize="20" Text="The event of"></Run>
                <Run FontSize="28" Text="{DynamicResource strBride}"></Run>
            </TextBlock>
        </Grid>
    </ControlTemplate>
</Page.Resources>

<Grid HorizontalAlignment="Center" VerticalAlignment="Top" Width="1000">
    <Button x:Name="btnWedding" HorizontalAlignment="Left" Margin="10,20,0,-49" VerticalAlignment="Top" Template="{StaticResource WeddingButtonBigTemplate}" Foreground="#FF2B4072" Width="380" Click="btnClick" />
</Grid>

我正在尝试访问名为textBlock2的 TextBlock 。
我试图覆盖OnApplyTemplate但得到了空值。

我试过:

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 为空(样本取自 MSDN)。
当然,ct# 都是空的。

我在这里缺少什么?

如果您已覆盖 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

如果你的例子是微软的例子,那么我建议你再读一遍。 你可能跳过了一些东西。

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

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

您的代码是正确的,但可能不在正确的位置... FindName仅在应用模板后才能工作。 通常,在自定义控件中覆盖OnApplyTemplate时使用它。 由于您不是在创建自定义控件,因此可以在按钮的 Loaded 事件中进行。

试试下面的代码。 这将返回模板化元素。

this.GetTemplateChild("ControlName");

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

private static DependencyObject RecursiveVisualChildFinder<T>(DependencyObject rootObject)  
{  
    var child = VisualTreeHelper.GetChild(rootObject, 0);  
    if (child == null) return null;  

    return child.GetType() == typeof (T) ? child : RecursiveVisualChildFinder<T>(child);  
}

你可以像这样使用它

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

如果您可以获得网格控制,请尝试使用以下代码

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

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

您可以让孩子处于您的情况的一种方法是继承按钮。 由于您不会修改按钮的任何其他属性或行为,因此新按钮将正常工作。 实际上,我从未使用过这种访问模板化子代的方法,因为我从未需要在控件类的范围之外使用它们。

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

<Page.Resources>
    <ControlTemplate x:Key="WeddingButtonBigTemplate" TargetType="Button">
        <Grid>
            <Image x:Name="imgNormal" Source="../Images/Married_button2.png"/>
            <TextBlock x:Name="textBlock2" Style="{StaticResource RegularBlueSpecialBoldText}" LineHeight="28" LineStackingStrategy="BlockLineHeight" HorizontalAlignment="Center" Margin="10,30,10,70" TextWrapping="Wrap" TextAlignment="Center" VerticalAlignment="Stretch" >
                <Run FontSize="20" Text="The event of"></Run>
                <Run FontSize="28" Text="{DynamicResource strBride}"></Run>
            </TextBlock>
        </Grid>
    </ControlTemplate>
</Page.Resources>

<Grid HorizontalAlignment="Center" VerticalAlignment="Top" Width="1000">
    <WeddingButton x:Name="btnWedding" HorizontalAlignment="Left" Margin="10,20,0,-49" VerticalAlignment="Top" Template="{StaticResource WeddingButtonBigTemplate}" Foreground="#FF2B4072" Width="380" Click="btnClick" />
</Grid>

对于其他可能仍然在这里绊倒的人。

默认情况下,我可以控制具有 Visibility="Collapsed" 的屏幕。 即使我在窗口构造函数中切换了可见性,它也没有初始化模板。 必须在 FindName() 之前在控件上调用 ApplyTemplate() 才能获得结果。

stationElement.ApplyTemplate();
var PART_DATA = stationElement.Template.FindName("PART_DATA", stationElement);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM