У меня есть GridView
с ColumnHeaderTemplate
Шаблон содержит путь с именем arrow
:
<DataTemplate x:Key="HeaderTemplate">
<DockPanel>
<Path DockPanel.Dock="Right" Margin="5,0,5,0" x:Name="arrow" StrokeThickness="1" Fill="Gray" Data="M 5,5 L 10,10 L 15,5 L 5,5" SnapsToDevicePixels="True"/>
</DockPanel>
</DataTemplate>
Шаблон назначается в представлении следующим образом:
<GridView ColumnHeaderTemplate="{StaticResource HeaderTemplate}">
GridView
находится внутри ListView
, который управляет событиями
GridViewColumnHeader.Click="ListView_ColumnHeaderClick"
private void ListView_ColumnHeaderClick(object sender, RoutedEventArgs e)
Когда событие запускается, я хочу найти элемент управления arrow
.
Согласно моим исследованиям, я должен использовать метод Template.FindName
, но пока мне не удалось это сделать.
Кажется, я не могу найти правильные объекты для использования с функцией, поэтому я никогда не нахожу элемент управления, который ищу.
Нет, метод FindName
, который вы имеете в виду, будет применяться к ControlTemplate
, а не DataTemplate
.
Для DataTemplate
вы должны перебирать детей вручную, используя VisualTreeHelper
.
Я не знаю, как вы прикрепили обработчик событий заголовка столбца, поэтому я предполагаю следующее:
<ListView ItemsSource="{Binding YourItemsSource}">
<ListView.Resources>
<DataTemplate x:Key="HeaderTemplate">
<DockPanel>
<Path DockPanel.Dock="Right" Margin="5,0,5,0" x:Name="arrow" StrokeThickness="1" Fill="Gray" Data="M 5,5 L 10,10 L 15,5 L 5,5" SnapsToDevicePixels="True"/>
</DockPanel>
</DataTemplate>
<Style x:Key="HeaderContainerStyle" TargetType="{x:Type GridViewColumnHeader}" BasedOn="{StaticResource {x:Type GridViewColumnHeader}}">
<EventSetter Event="Click" Handler="ListView_ColumnHeaderClick"/>
</Style>
</ListView.Resources>
<ListView.View>
<GridView ColumnHeaderTemplate="{StaticResource HeaderTemplate}"
ColumnHeaderContainerStyle="{StaticResource HeaderContainerStyle}">
<!-- ...your column definitions. -->
</GridView>
</ListView.View>
</ListView>
Вы должны создать собственный метод для рекурсивного обхода визуального дерева заголовка столбца представления сетки, который проверяет тип и имя дочерних элементов, чтобы получить правильный.
public T GetChild<T>(DependencyObject dependencyObject, string name) where T : FrameworkElement
{
if (dependencyObject == null)
return null;
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
{
var child = VisualTreeHelper.GetChild(dependencyObject, i);
if (child is T frameworkElement && frameworkElement.Name.Equals(name))
return frameworkElement;
var nextChild = GetChild<T>(child, name);
if (nextChild != null)
return nextChild;
}
return null;
}
Затем в обработчике событий вы можете передать sender
, который является заголовком столбца.
private void ListView_ColumnHeaderClick(object sender, RoutedEventArgs e)
{
var gridViewColumnHeader = (GridViewColumnHeader)sender;
var arrow = GetChild<Path>(gridViewColumnHeader, "arrow");
// ... do something with arrow.
return;
}
Хотя это решение работает и является законным и официально задокументированным способом решения вашей проблемы, обычно вам не нужно перемещаться по визуальному дереву таким образом. В большинстве случаев в этом нет необходимости, так как многие вопросы можно решить изящнее и проще с помощью привязки данных.