Как получить экземпляр Panel, который содержит содержимое ItemsControl? - PullRequest
22 голосов
/ 20 января 2011

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

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

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

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

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

Ответы [ 3 ]

17 голосов
/ 20 января 2011

Это немного сложно, так как вы не знаете имя Panel, поэтому вы не можете использовать 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 не всегда используется. См. этот ответ Яна Гриффитса для хорошего объяснения.

3 голосов
/ 20 января 2011

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

2 голосов
/ 26 января 2012
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, используя отражение?

...