Подтвердить что ты не робот

Как расширить WPF TreeView на один клик элемента

Теперь вам нужно дважды щелкнуть или щелкнуть значок+. Есть ли способ сделать это, если пользователь нажимает в любом месте на node, он расширяется?

4b9b3361

Ответ 1

Возможно, это не самое элегантное решение, но это работает:

    static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
    {
        while (source != null && source.GetType() != typeof(T))
            source = VisualTreeHelper.GetParent(source);

        return source;
    }

то в обработчике TreeViewItem.Selected:

        private void Treeview_Selected(object sender, RoutedEventArgs e)
        {
            var treeViewItem = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) as TreeViewItem;
            if (treeViewItem != null) treeViewItem.IsExpanded = true;
        }

Маска VisualUpwardSearch берется здесь: Выберите TreeView Node правой кнопкой мыши перед отображением ContextMenu

Привет

Ответ 2

У меня была такая же проблема, и я нашел хорошее решение благодаря fooobar.com/questions/425777/....

В элементе tree.xaml TreeView вы можете напрямую подключиться к событию TreeViewItem Selected:

<TreeView ItemsSource="{StaticResource Array}" TreeViewItem.Selected="TreeViewItem_Selected"/>

Затем в вашем файле control.xaml.cs позади вы можете захватить выбранный TreeViewItem из RoutedEventArgs и установить его в IsExpanded:

private void TreeViewItem_Selected(object sender, RoutedEventArgs e)
{
    TreeViewItem tvi = e.OriginalSource as TreeViewItem;

    if (tvi == null || e.Handled) return;

    tvi.IsExpanded = !tvi.IsExpanded;
    e.Handled = true;
}

Приятный и чистый. Надеюсь, это поможет кому-то!

Ответ 3

У меня была та же проблема, и я сделал это с функциональной функцией Style, так что вам не нужно обрабатывать событие.

Я определил стиль для TreeViewItem

<Style x:Key="{x:Type TreeViewItem}" TargetType="{x:Type TreeViewItem}">
    <!--<Setter Property="FocusVisualStyle" Value="{StaticResource TreeViewItemFocusVisual}"/>-->
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TreeViewItem}">
                        <CheckBox Style="{StaticResource TreeViewItemCB}" IsChecked="{Binding Path=IsExpanded,Mode=OneWayToSource,RelativeSource={RelativeSource TemplatedParent}}"  ClickMode="Press">
                            <Grid Background="{StaticResource TreeViewItemBackground}" Margin="0">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition/>
                            </Grid.RowDefinitions> 
                            <Border Name="Bd">
                                    <ContentPresenter x:Name="PART_Header" ContentSource="Header"/>
                            </Border>
                            <ItemsPresenter x:Name="ItemsHost" Grid.Row="1"/>
                            </Grid>
                        </CheckBox>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Важной частью является определение checkBox в ControlTemplate и привязка к нему. Когда CheckBox установлен, элемент будет расширен одним щелчком мыши.

<CheckBox Style="{StaticResource TreeViewItemCB}" IsChecked="{Binding Path=IsExpanded,Mode=OneWayToSource,RelativeSource={RelativeSource TemplatedParent}}"  ClickMode="Press">

это стиль для checkbox, так что он растягивается и не отображает окно с штрихом.

<Style x:Key="TreeViewItemCB" TargetType="CheckBox" BasedOn="{StaticResource baseStyle}">
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="VerticalAlignment" Value="Stretch"/>
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="CheckBox">
                <ContentPresenter VerticalAlignment="Stretch" HorizontalAlignment="Stretch" RecognizesAccessKey="True"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Ответ 4

@BJennings дал отличный ответ. Однако, если вы хотите развернуть или свернуть уже выбранный элемент, это не сработает. Чтобы улучшить это, вы можете просто добавить: tvi.IsSelected = false; (если вам все равно, находится ли элемент в выбранном состоянии.)

Итак, все коды выглядят так:

private void TreeViewItem_Selected(object sender, RoutedEventArgs e)
{
    TreeViewItem tvi = e.OriginalSource as TreeViewItem;

    if (tvi == null || e.Handled) return;

    tvi.IsExpanded = !tvi.IsExpanded;
    tvi.IsSelected = false;
    e.Handled = true;
}

Ответ 5

Принятое решение имеет странное поведение при навигации с помощью клавиатуры и не сбрасывает элемент, когда он уже выбран. Кроме того, просто выведите новый класс из TreeViewItem и переопределите метод MouseLeftButtonDown. Вам также необходимо установить TreeView.ItemsSource в коллекцию нового класса TreeViewItem.

protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
    if (!e.Handled && base.IsEnabled)
    {
        this.IsExpanded = !this.IsExpanded;
        e.Handled = true;
    }
    base.OnMouseLeftButtonDown(e);
}

Ответ 6

Другой подход - использовать Attached propperties.

public class VirtualOneClickExpandButtonBehavior : DependencyObject
{
    public static bool GetEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(EnabledProperty);
    }

    public static void SetEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(EnabledProperty, value);
    }


    public static readonly DependencyProperty EnabledProperty =
        DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(VirtualOneClickExpandButtonBehavior), 
            new UIPropertyMetadata(false, EnabledPropertyChangedCallback
                ));

    private static void EnabledPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        var treeView = dependencyObject as TreeView;

        if (treeView == null) return;

        treeView.MouseUp += TreeView_MouseUp;
    }

    private static void TreeView_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        var treeViewItem = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) as TreeViewItem;
        if (treeViewItem != null) treeViewItem.IsExpanded = !treeViewItem.IsExpanded;
    }

    static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
    {
        while (source != null && source.GetType() != typeof(T))
            source = VisualTreeHelper.GetParent(source);

        return source;
    }
}

И тогда вы можете использовать его вот так.

<TreeView controls:VirtualOneClickExpandButtonBehavior.Enabled="true" ItemsSource="{Binding HierarchicalModel}"/>

Это хороший подход, если вы используете шаблон MVVM, потому что вам не нужен код.

И нападает на Маркуста для его VisualUpwardSearch (источник DependencyObject)

Ответ 7

Основываясь на ответе BJennings, если я хочу поместить функцию private void TreeViewItem_Selected(object sender, RoutedEventArgs e) в статический класс, как я могу это сделать? Я старался:

xmlns:wpfcommonhelpers="clr-namespace:WPFCommon.Helpers"


<TreeView ItemsSource="{StaticResource Array}" TreeViewItem.Selected="wpfcommonhelpers:TreeViewItemHelper.TreeViewItem_Selected"/>



public static class TreeViewItemHelper
{
    public static void TreeViewItem_Selected(object sender, RoutedEventArgs e)
    {
        var tvi = e.OriginalSource as TreeViewItem;

        if (tvi == null || e.Handled) return;

        tvi.IsExpanded = !tvi.IsExpanded;
        tvi.IsSelected = false;
        e.Handled = true;
    }
}

Но не работает... Есть идеи? Спасибо

Ответ 8

<TreeView.ItemContainerStyle>
  <Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="Cursor" Value="Hand" />
    <EventSetter Event="MouseUp" Handler="TreeViewItem_Click"/>
  </Style>
</TreeView.ItemContainerStyle>


private void TreeViewItem_Click(object sender, MouseButtonEventArgs e)
        {
            ((TreeViewItem) sender).IsExpanded = !((TreeViewItem) sender).IsExpanded;
            Thread.Sleep(700);
        }

Вот ответ, Наслаждайся

Ответа на этот вопрос: Ali Rahimy