Как получить экземпляр 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
.
В случае, если это неясно, прокомментируйте, я думаю, что есть очень простое решение. Если это кажется сложным, только потому, что я не могу его правильно объяснить.
Ответы
Ответ 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 с помощью отражения?