簡體   English   中英

ItemsControl:如何在ItemsPanelTemplate中使用FindName來訪問Panel

[英]ItemsControl: How To Use FindName within ItemsPanelTemplate to access Panel

<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以在更改子項時設置事件。

[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的時間?

另一種選擇是在.ApplyTemplate()上調用.ApplyTemplate() ,同時仍然在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);
        }
    }

弄清楚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);
    }

FindName方法只能發現在已經擴大,模板名稱ItemsPanel通過擴大ItemsPresenter ,而不是ItemsControl 在您的情況"PART_StackPanel"永遠是對孩子"PART_Presenter"這樣你就可以得到這樣的一個引用:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM