【问题标题】:How to get instance of Panel that holds content of ItemsControl?如何获取包含 ItemsControl 内容的 Panel 实例?
【发布时间】:2011-06-12 07:03:40
【问题描述】:

每个ItemsControl 都将其内容存储在 Panel 中,对吗?我们可以像这样指定要在 XAML 中使用的面板:

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

我的问题是如何获取在特定 ItemsControlItemsPanel 属性(类型为 ItemsPanelTemplate)中使用的 Panel 的实例?例如上面的代码示例中的ListView 调用LView

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

如果不清楚请发表评论,我认为有非常简单的解决方案。如果它看起来很复杂,那只是因为我无法正确解释它。

【问题讨论】:

  • 您想从哪里获取该实例?是来自ItemsControl 还是来自其中的某个项目模板?
  • 完全来自ItemsPanelTemplate。我绝对不想从项目模板中获取它。
  • 我是否正确理解了您的问题,还是您正在寻找其他内容?
  • @Meleak:在pivotnig 的回答之后,我能够找到一些解决方案——我所需要的只是有一个VisualTreeHelper 类。我的代码看起来与您提供的非常相似,我不确定差异 - 我不确定我的代码是否总是有效(可能存在一些我不知道的泄漏......)。一段时间后我会接受其中一个答案。

标签: c# .net wpf controls custom-controls


【解决方案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。请参阅 Ian Griffiths 的 this answer 以获得很好的解释。

【讨论】:

    【解决方案2】:

    我无法为您提供工作代码,但请看一下 VisualTreeHelper class。 使用VisualTreeHelper 类,您可以遍历可视化树到您的模板和面板。

    【讨论】:

      【解决方案3】:
      protected Panel ItemsHost {
          get {
              return (Panel) typeof (MultiSelector).InvokeMember("ItemsHost",
                  BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance,
                  null, this, null);
          }
      }
      

      这在我的ItemsControl 中就像一个魅力!也就是说,它内部的Panel 上确实有IsItemsHost="True",但即使没有它也可以工作。

      技巧来自这个帖子:Can I access ItemsHost of ItemsControl using reflection?

      【讨论】:

        【解决方案4】:
           private object FindItemControl(ItemsControl itemsControl, string controlName, object item)
            {
                ContentPresenter container = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter;
                container.ApplyTemplate();
                return container.ContentTemplate.FindName(controlName, container);
            }
        

        【讨论】:

          猜你喜欢
          • 2015-09-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多