如何在单击项目时展开WPF TreeView

时间:2010-05-27 14:23:03

标签: wpf treeview

现在您必须双击或单击+图标。如果用户点击它展开的节点上的任何地方,有没有办法实现它?

7 个答案:

答案 0 :(得分:16)

由于another StackOverflow post,我遇到了同样的问题并找到了一个很好的解决方案。

在control.xaml的TreeView元素中,您可以直接挂钩到TreeViewItem的Selected事件:

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

然后在您的control.xaml.cs代码中,您可以从RoutedEventArgs中获取所选的TreeViewItem并将其设置为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;
}

干净整洁。希望这有助于某人!

答案 1 :(得分:5)

也许不是最优雅的解决方案,但这有效:

    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魔术从这里获取:Select TreeView Node on right click before displaying ContextMenu

此致

答案 2 :(得分:2)

我遇到了同样的问题,我使用了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>

重要的部分是在ControlTemplate中定义checkBox并与之绑定。选中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>

答案 3 :(得分:1)

@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;
}

答案 4 :(得分:0)

当您使用键盘导航时,已接受的解决方案具有奇怪的行为,并且在已经选择项目时不会折叠该项目。或者,只需从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);
}

答案 5 :(得分:0)

另一个方法是使用附加属性。

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模式,这是一个很好的方法,因为您不需要代码隐藏。

向Markust寻求他的VisualUpwardSearch(DependencyObject源代码)

答案 6 :(得分:-1)

<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