2013-10-01 36 views
19

內部控制這是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#全爲空。

我在這裏錯過了什麼?

+2

我懷疑你的按鈕沒有'加載(在UI上呈現)'呢。只有在模板應用於按鈕時,您的代碼纔會返回null。 –

+0

由於您尚未在xaml聲明中爲您的網格指定'x:Name',因此'gridInTemplate'爲null。 –

+1

我碰到類似的問題,不得不調用'UpdateLayout'來解決@RohitVats提到的問題。 – Chris

回答

1

如果你能得到的網格控件,然後嘗試使用下面的代碼

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

我的錯誤,網格爲空,雖然我拿了來自MSDN示例的代碼。問題相應更新。 – toy4fun

2

可以使用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 
} 
+0

我收到以下異常:'指定的索引超出範圍或索引處的子項爲空。如果VisualChildrenCount返回0,則不要調用此方法,這表示Visual沒有子項.' – toy4fun

+0

同樣的問題在這裏,添加了一個賞金 – DaveO

+0

'var ct0 = btnWedding.Template.FindName(「textBlock2」,btnWedding);'對我來說工作正常...你能分享你的代碼中你想要獲得文本塊的位置嗎? – Nitin

4

你的代碼是正確的,但可能不會在正確的地方... FindName後,才工作模板已被應用。通常,您在自定義控件中覆蓋OnApplyTemplate時使用它。由於您沒有創建自定義控件,因此可以在按鈕的Loaded事件中執行此操作。

18

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

如果你的例子是微軟的例子那麼我建議你讀一遍。你可能跳過了一些東西。例如創作自定義控制時使用GetTemplateChild() -

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

綜上所述OnApplyTemplate,並在其他情況下使用Template.FindName。

+0

這對我有幫助。通過重寫'OnApplyTemplate'(而不是'OnTemplateChange')使其工作。 – Crypt32

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> 
4

請嘗試以下代碼。這將返回模板元素。

this.GetTemplateChild("ControlName");