2011-01-27 58 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

您需要訂閱哪些事件? – 2011-01-27 07:09:22

回答

0

FindName方法只能找到已擴展的模板中的名稱,而ItemsPanelItemsPresenter擴展而不是ItemsControl。在您的情況"PART_StackPanel"永遠是"PART_Presenter"的孩子這樣你可以得到一個參考,以這樣的:

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

仍在該行上收到ArgumentOutOfRangeException。指定的索引超出範圍或索引處的子項爲空。 如果VisualChildrenCount返回0,則不要調用此方法,表示Visual沒有子項。 參數名稱:index 實際值爲0. 還確切指出擴展意味着什麼時引用模板。謝謝您的幫助。是否還有另一點我可以期望找到PART_StackPanel添加到演示者? – Case 2011-01-27 12:42:24

+0

您可以將`StackPanel`移動到`ControlTemplate`中,而不是使用`ItemsPresenter`。或者你可以在`ItemsPresenter`的`Loaded`事件中尋找`StackPanel`。展開意味着誰正在應用該模板。 `ItemsControl`不適用於`ItemsPanel`模板。 – 2011-01-27 16:54:49

1

想通了,Loaded事件是一個等待在ItemsPanelTemplate。我能夠使用TemplatePart名稱找到StackPanel。感謝Rick建議應該在Presenter中找到StackPanel。

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

另一種方法是調用.ApplyTemplate()在ItemsPresenter同時還在ItemControl的OnApplyTemplate方法。然後致電.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); 
     } 
    } 
相關問題