Как получить текстовое поле для заполнения элемента дерева - PullRequest
0 голосов
/ 24 мая 2018

У меня есть TreeView с тремя уровнями, управляемыми HierarchicalDataTemplate.Вот частичный листинг xaml:

<TreeView
    Name="TreeView"
    ItemsSource="{Binding GTOs}"
    ScrollViewer.HorizontalScrollBarVisibility="Hidden">
    <TreeView.ItemsPanel>
        <ItemsPanelTemplate>
            <!--  This binding prevents the TreeView from slipping over to the right when an item is clicked.  -->
            <StackPanel MaxWidth="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=1}}" />
        </ItemsPanelTemplate>
    </TreeView.ItemsPanel>

    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:TreeGTOViewModel}" ItemsSource="{Binding Children}">
            <TextBlock
                Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeView}}, Path=ActualWidth}"
                MouseDown="TextBlock_MouseDown"
                Tag="{Binding Uri}"
                Text="{Binding Title}" />
        </HierarchicalDataTemplate>

Атрибут Binding в Width TextBlock гарантирует, что каждый TreeViewItem предполагает полную ширину контейнера TreeView (а не только ширинутекстовое поле).В сочетании со стилем Material Design это дает хорошие эффекты затенения, когда мышь наведена на определенный элемент дерева.

Есть только одна проблема.Хотя я могу получить ширину, чтобы принять полную ширину TreeViewItem, я не могу сделать то же самое для высоты.Это означает, что пользователь может щелкнуть рядом с краем элемента TreeView и увидеть все эффекты, как если бы этот элемент был нажат, но событие MouseDown не срабатывает.

Это область, которая должен быть кликабельным (пунктирная красная линия):

enter image description here

Это та область, которая фактически кликабельна (внешняя граница текстаBox):

enter image description here

Я пробовал несколько различных подходов, включая этот:

VerticalAlignment="Stretch"

и этот:

Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=ActualHeight}"

но они либо не действуют, либо неожиданно нарушают TreeView.Я думаю, что часть проблемы - обычная странная высота StackPanel, которая используется в ItemsPanelTemplate.

Как я могу получить TextBox в каждом TreeViewItem, чтобы принять высоту фактического TreeViewItem?

Ниже приведено изображение соответствующей части визуального дерева, изTreeView вниз до интерактивного текстового поля.Элемент Ripple является объектом MaterialDesignThemes.Wpf.Ripple.

enter image description here

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Я сделал очень простой тестовый проект MahApp с деревом и одним деревом (без привязки).

В Live Visual Tree для PART_Header было установлено значение VerticalAlignment Center.Если я изменил его на Растянуть (используя Live Property Explorer), текстовый блок заполнил пространство по вертикали.

Итак, я использовал Outline документа в VS для редактирования копии шаблона древовидной структуры.Внутри этого я увидел <Setter Property="VerticalContentAlignment" Value="Center">, поэтому я решил установить его на Stretch в TreeView, и он, похоже, сработал.

<TreeView x:Name="TreeView"
  ScrollViewer.HorizontalScrollBarVisibility="Hidden"
  VerticalContentAlignment="Stretch">
0 голосов
/ 24 мая 2018

Ну, я решил это, выбрав другой маршрут.Вместо того чтобы перехватывать событие MouseDown в текстовом блоке, я собираюсь перехватить событие SelectedItemChanged в древовидном представлении.

    <TreeView
        ItemsSource="{Binding GTOs}"
        SelectedItemChanged="TreeView_SelectedItemChanged">

RoutedPropertyChangedEventArgs события SelectedItemChanged содержитViewModel для этого конкретного TreeViewItem, который возвращает свойство Uri, необходимое для навигации (ранее я связывал это свойство со свойством TextBox's Tag).

Новый обработчик событий выглядит следующим образом:

private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    dynamic viewModel = e.NewValue;
    var uri = viewModel.Uri;
    (DataContext as TreeViewModel).Navigate(uri);
}

Каждый уровень дерева содержит свой тип ViewModel, но все они имеют свойство Uri, поэтому привязка dynamic обеспечивает необходимое поведение "не важно, какой это тип".

Теперь я могу удалить привязку Tag и событие MouseDown из TextBlock.

    <HierarchicalDataTemplate DataType="{x:Type local:TreeGTOViewModel}" ItemsSource="{Binding Children}">
        <TextBlock
            Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeView}}, Path=ActualWidth}"
            Text="{Binding Title}" />

, и элементы древовидного представления теперь реагируют правильно, независимо от того, где они нажаты.

...