簡體   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