如何获取包含ItemsControl内容的面板实例?

时间:2022-08-02 17:02:58

Every ItemsControl has its content stored in Panel right ? We can specify the panel to be used in XAML like this:

每个项目控制都有其内容存储在面板中,对吗?我们可以指定在XAML中使用的面板如下:

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

My question is how to get instance of Panel that is used in the ItemsPanel property (of type ItemsPanelTemplate) of the particular ItemsControl ? For example ListView called LView from above code sample?

我的问题是如何获得在ItemsPanel属性(类型为ItemsPanelTemplate)中使用的面板实例?例如,ListView从上面的代码示例中调用LView ?

I cannot use Name property or x:Name, this must work for any ItemsControl even those using default ItemsPanel.

我不能使用Name属性或x:Name,这必须适用于任何ItemsControl,即使是使用默认ItemsPanel的。

In the case its not clear please comment, I think there is very simple solution. If it seems to be complicated that's only because I cannot explain it properly.

对于不清楚的情况,请评论,我认为有很简单的解决办法。如果它看起来很复杂,那只是因为我不能正确地解释它。

3 个解决方案

#1


15  

It's a little tricky since you don't know the name of the Panel so you can't use FindName etc. This will work for most cases where an ItemsPresenter is present

这有点棘手,因为您不知道面板的名称,所以不能使用FindName等。这对于存在ItemsPresenter的大多数情况都适用

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

An implementation of GetVisualChild

的一个实现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;
}

However, the ItemsPanel isn't always used. See this answer by Ian Griffiths for a great explanation.

然而,ItemsPanel并不总是被使用。请参阅伊恩·格里菲思的回答,以获得一个很好的解释。

#2


3  

I can't provide you with working code, but have a look at VisualTreeHelper class. With the VisualTreeHelper class you can traverse the visual tree down to your template and panel.

我不能为您提供工作代码,但请查看VisualTreeHelper类。使用VisualTreeHelper类,您可以遍历可视化树到模板和面板。

#3


2  

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

This works like a charm in my ItemsControl! That said, it does have IsItemsHost="True" on the Panel inside, but might even work without it.

这在我的物品控制中很有用!也就是说,它内部的面板上确实有IsItemsHost=“True”,但如果没有它,它甚至可以工作。

Trick is from this thread: Can I access ItemsHost of ItemsControl using reflection?

技巧来自这个线程:我可以使用反射访问ItemsControl的ItemsHost吗?

#1


15  

It's a little tricky since you don't know the name of the Panel so you can't use FindName etc. This will work for most cases where an ItemsPresenter is present

这有点棘手,因为您不知道面板的名称,所以不能使用FindName等。这对于存在ItemsPresenter的大多数情况都适用

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

An implementation of GetVisualChild

的一个实现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;
}

However, the ItemsPanel isn't always used. See this answer by Ian Griffiths for a great explanation.

然而,ItemsPanel并不总是被使用。请参阅伊恩·格里菲思的回答,以获得一个很好的解释。

#2


3  

I can't provide you with working code, but have a look at VisualTreeHelper class. With the VisualTreeHelper class you can traverse the visual tree down to your template and panel.

我不能为您提供工作代码,但请查看VisualTreeHelper类。使用VisualTreeHelper类,您可以遍历可视化树到模板和面板。

#3


2  

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

This works like a charm in my ItemsControl! That said, it does have IsItemsHost="True" on the Panel inside, but might even work without it.

这在我的物品控制中很有用!也就是说,它内部的面板上确实有IsItemsHost=“True”,但如果没有它,它甚至可以工作。

Trick is from this thread: Can I access ItemsHost of ItemsControl using reflection?

技巧来自这个线程:我可以使用反射访问ItemsControl的ItemsHost吗?