これは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
を上書きしようとしましたが、nullになりました。
私はもう試した:
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はnullです(MSDNから取得したサンプル)。
もちろん、ct#はすべてnullです。
ここで何が欠けていますか?
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
まとめると、カスタムコントロールを作成するときにGetTemplateChild()を使用します。 OnApplyTemplate、およびその他の状況ではTemplate.FindNameを使用します。
次のコードを試してください。これはテンプレート化された要素を返します。
this.GetTemplateChild("ControlName");
あなたのコードは正しいですが、おそらく正しい場所にありません... FindName
は、テンプレートが適用された後にのみ機能します。通常、カスタムコントロールでOnApplyTemplate
をオーバーライドするときに使用します。カスタムコントロールを作成していないため、ボタンのLoadedイベントで行うことができます。
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)」メソッドは、ボタン/コントロールが名前を解決するために使用されるレイアウトの名前スコープを使用します。つまり、これを使用して、アプリケーションレイアウトのグリッドまたはスタックパネルで子を見つけることができます。しかし、同じものを使用して、アプリケーションレイアウトで使用したコントロールの子を見つけることはできません(テンプレート化された子供の名前が別のスコープにあるため)
自分の状況で子供を取得する1つの方法は、ボタンを継承することです。ボタンの他のプロパティや動作は変更しないので、新しいボタンは通常のボタンとして機能します。実際には、テンプレートの子にアクセスするこのようなメソッドを使用したことはありません。これは、コントロールのクラスのスコープ外で使用する必要がなかったためです。
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>