Подтвердить что ты не робот

Как получить экземпляр Panel, который содержит содержимое ItemsControl?

Каждый ItemsControl имеет свой контент, сохраненный в панели справа? Мы можем указать панель, которая будет использоваться в XAML, например:

<ListView Name="LView">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate >
            <StackPanel/>
        </ItemsPanelTemplate>
     </ListView.ItemsPanel>
</ListView>

Мой вопрос: как получить экземпляр Panel, который используется в свойстве ItemsPanel (типа ItemsPanelTemplate) конкретного ItemsControl? Например ListView, называемый LView из предыдущего примера кода?

Я не могу использовать свойство Name или x:Name, это должно работать для любого ItemsControl даже тех, которые используют по умолчанию ItemsPanel.

В случае, если это неясно, прокомментируйте, я думаю, что есть очень простое решение. Если это кажется сложным, только потому, что я не могу его правильно объяснить.

4b9b3361

Ответ 1

Это немного сложно, так как вы не знаете имя панели, поэтому вы не можете использовать FindName и т.д. Это будет работать в большинстве случаев, когда присутствует ItemsPresenter

private Panel GetItemsPanel(DependencyObject itemsControl)
{
    ItemsPresenter itemsPresenter = GetVisualChild<ItemsPresenter>(itemsControl);
    Panel itemsPanel = VisualTreeHelper.GetChild(itemsPresenter, 0) as Panel;
    return itemsPanel;
}

Реализация GetVisualChild

private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
    T child = default(T);

    int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < numVisuals; i++)
    {
        Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
        child = v as T;
        if (child == null)
        {
            child = GetVisualChild<T>(v);
        }
        if (child != null)
        {
            break;
        }
    }
    return child;
}

Однако элемент ItemsPanel не всегда используется. См. этот ответ Яна Гриффитса за отличное объяснение.

Ответ 2

Я не могу предоставить вам рабочий код, но взгляните на класс VisualTreeHelper. С классом VisualTreeHelper вы можете пересечь визуальное дерево до вашего шаблона и панели.

Ответ 3

protected Panel ItemsHost {
    get {
        return (Panel) typeof (MultiSelector).InvokeMember("ItemsHost",
            BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance,
            null, this, null);
    }
}

Это работает как прелесть в моем ItemsControl! Тем не менее, он имеет IsItemsHost="True" на Panel внутри, но может даже работать без него.

Трюк из этой темы: Могу ли я получить доступ к ItemsHost of ItemsControl с помощью отражения?