Как найти элемент управления DataTemplate внутри события Click

У меня есть 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, но пока мне не удалось это сделать. Кажется, я не могу найти правильные объекты для использования с функцией, поэтому я никогда не нахожу элемент управления, который ищу.

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
0
25
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Нет, метод 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;
}

Хотя это решение работает и является законным и официально задокументированным способом решения вашей проблемы, обычно вам не нужно перемещаться по визуальному дереву таким образом. В большинстве случаев в этом нет необходимости, так как многие вопросы можно решить изящнее и проще с помощью привязки данных.

Другие вопросы по теме