ちょっとした覚書。 TemplateからNameを元にコントロールを探すにはControlTemplate.FindNameメソッドまたはFrameworkElement.GetTemplateChildメソッドを使うようです。 FrameworkElement.FindNameメソッドはTemplateの中までは探してくれないらしい。 参考サイトはこちら。
1つのTemplateが複数のコントロールに適用された場合、同じNameのコントロールがその数だけ作成されます。 なのでNameでコントロールを探すときはVisualTreeHelperを使うのではなく、名前スコープを考慮したこれらのメソッドを使うものなんだそうです。 気付くのに遅れて無駄足を踏んでしまった...
メソッドということでxamlからは使用できません。
使用例はこんな感じ。
public class CustomControl1 : Button
{
private Label _hoge;
public CustomControl1()
{
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Updateなんたら();
}
protected override void OnTemplateChanged(ControlTemplate oldTemplate, ControlTemplate newTemplate)
{
if (IsLoaded)
Updateなんたら();
}
private void Updateなんたら()
{
// カスタムコントロール内で使えるprotectedメソッド
Button foo = this.GetTemplateChild("foo") as Button;
// カスタムコントロールではない場合はこちらを使う
Border bar = _hoge.Template.FindName("bar", _hoge) as Border;
}
}
インスタンス化してからしか使えないのでこうなります。 カスタムコントロールのOnTemplateChangedメソッドはLoadedイベントの前に呼ばれるため、IsLoadedでインスタンスがあるかどうかを判断します。
どうでもいいけど、名前空間と名前スコープって紛らわしいですよね? そうでもない?

