2011-01-27 27 views
2
<Style TargetType="{x:Type local:CustomItemsControl}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate> 
       <ScrollViewer> 
        <ItemsPresenter x:Name="PART_Presenter"/> 
       </ScrollViewer> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
    <Setter Property="ItemsPanel"> 
     <Setter.Value> 
      <ItemsPanelTemplate> 
       <StackPanel x:Name="PART_StackPanel" IsItemsHost="True"/> 
      </ItemsPanelTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

子が変更されたときにイベントを設定するためにStackPanelにアクセスしようとしています。ItemsControl:ItemsPanelTemplate内でFindNameを使用してパネルにアクセスする方法

[TemplatePartAttribute(Name = "PART_StackPanel", Type = typeof(StackPanel))] 
[TemplatePartAttribute(Name = "PART_Presenter", Type = typeof(ItemsPresenter))] 
public class CustomItemsControl: ItemsControl 
{ 
    public override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 
     var presenter = (ItemsPresenter)this.Template.FindName("PART_Presenter", this); 
     var stackPanel = (StackPanel)this.ItemsPanel.FindName("PART_StackPanel",this); 
    } 
} 

StackPanelを見つけようとすると例外が発生します。

と、InvalidOperationException:

この操作は、このテンプレートが適用されている要素で有効です。

ItemsPanelTemplate内でTemplatePartを見つける方法があるかどうかを教えてください。そしてItemsPanelTemplateがいつ適用されるのか分かりますか?

+0

どのようなイベントを購読する必要がありますか? –

答えて

0

ItemsPanelは、ItemsControlではなく、ItemsPresenterで拡張されたテンプレート内の名前のみを検索します。あなたの状況では"PART_StackPanel"は常に"PART_Presenter"の子供はあなたがこのようにそれへの参照を取得することができようになります。

var stackPanel = (StackPanel)VisualTreeHelper.GetChild(presenter, 0); 
+0

その行で引き続きArgumentOutOfRangeExceptionを取得しています。指定されたインデックスが範囲外です。または、indexの子がnullです。 VisualChildrenCountがゼロを返し、Visualに子がないことを示す場合は、このメソッドを呼び出さないでください。 パラメータ名:index 実際の値は0です。 テンプレートを参照する際にどのような拡張が意味するのか正確にはわかりません。助けてくれてありがとう。 PART_StackPanelがプレゼンターに追加されることを期待できる別のポイントはありますか? – Case

+0

'StackPanel'を' ControlTemplate'に移動し、 'ItemsPresenter'を使用することはできません。あるいは、 'ItemsPresenter'の' Loaded'イベントで 'StackPanel'を探すことができます。拡張とは、テンプレートの適用を行っている人を意味します。 'ItemsControl'は' ItemsPanel'テンプレートを適用しません。 –

1

LoadedイベントがItemsPanelTemplateのを待つために一つであったことを考え出しました。 TemplatePart名を使用してStackPanelを見つけることができました。 StackPanelがPresenter内に見つかるはずだとRickに感謝します。

protected override void OnInitialized(EventArgs e) 
    { 
     base.OnInitialized(e); 
     this.Loaded += new Accordion_Loaded; 
    } 

    void Accordion_Loaded(object sender, RoutedEventArgs e) 
    { 
     var presenter = (ItemsPresenter)this.Template.FindName("PART_Presenter", this); 
     var stackPanel = (StackPanel)this.ItemsPanel.FindName("PART_StackPanel", presenter); 
    } 
4

別のオプションは、まだItemControlのOnApplyTemplate方法におけるながらItemsPresenterに.ApplyTemplate()を呼び出すことです。その後、.FindNameへの呼び出しは成功します。

[TemplatePartAttribute(Name = "PART_StackPanel", Type = typeof(StackPanel))] 
    [TemplatePartAttribute(Name = "PART_Presenter", Type = typeof(ItemsPresenter))] 
    public class CustomItemsControl : ItemsControl 
    { 
     public override void OnApplyTemplate() 
     { 
      base.OnApplyTemplate(); 
      var presenter = (ItemsPresenter)this.Template.FindName("PART_Presenter", this); 
      presenter.ApplyTemplate(); 
      var stackPanel = (StackPanel)this.ItemsPanel.FindName("PART_StackPanel", presenter); 
     } 
    } 
+0

完璧な答え! –

+0

優れています。これは機能します。 –

関連する問題