ItemsControl: как использовать FindName в ItemsPanelTemplate для доступа к панели - PullRequest
3 голосов
/ 27 января 2011
<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:

Эта операция действительна только для элементов, к которым применен этот шаблон.

Пожалуйста, сообщите, если есть способ найти TemplatePartв шаблоне ItemsPanelTemplate.И когда я должен знать, когда применяется ItemsPanelTemplate?

Ответы [ 3 ]

5 голосов
/ 14 марта 2013

Другим вариантом является вызов .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);
        }
    }
1 голос
/ 27 января 2011

Выяснилось, что событие Loaded было тем, которое нужно ожидать на ItemsPanelTemplate.Я могу найти StackPanel, используя имя TemplatePart.Спасибо Рику за предложение, что StackPanel должен быть найден в Presenter.

    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);
    }
0 голосов
/ 27 января 2011

Метод FindName находит только имена в расширенном шаблоне, а ItemsPanel расширяется на ItemsPresenter, а не ItemsControl. В вашей ситуации "PART_StackPanel" всегда будет дочерним по отношению к "PART_Presenter", поэтому вы можете получить ссылку на него следующим образом:

    var stackPanel = (StackPanel)VisualTreeHelper.GetChild(presenter, 0);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...