Select node in treeView on right click MVVM

前端 未结 2 589
孤街浪徒
孤街浪徒 2021-01-13 09:12

I want to select a node of tree view on right click. I am using MVVM pattern and don\'t want to achieve this in code behind. Here is my XAML for tree view.

&         


        
相关标签:
2条回答
  • 2021-01-13 09:27

    You can use interactivity

    xmlns:interactive="http://schemas.microsoft.com/expression/2010/interactivity"
    

    The xaml:

    <TreeView x:Name="TreeView" HorizontalAlignment="Left" Height="373" Margin="13,15,0,0" VerticalAlignment="Top" Width="373" Background="#29292f" 
                      Foreground="White" BorderBrush="Transparent" BorderThickness="0" ItemsSource="{Binding EmtRoot}" FontSize="24" >
                <interactive:Interaction.Triggers>
                    <interactive:EventTrigger EventName="SelectedItemChanged">
                        <interactive:InvokeCommandAction Command="{Binding SelectItemCommand}" CommandParameter="{Binding ElementName=TreeView,Path=SelectedItem}"/>
                    </interactive:EventTrigger> 
                </interactive:Interaction.Triggers>
                <TreeView.Resources>
                    <HierarchicalDataTemplate DataType="{x:Type models:EmtRootModel}" ItemsSource="{Binding Entities}">
                        <TextBlock Text="Root" Foreground="White" ContextMenu="{StaticResource ContextMenuLevel0}"/>
                    </HierarchicalDataTemplate>
                    <HierarchicalDataTemplate DataType="{x:Type models:EntityModel}" ItemsSource="{Binding Slides}">
                        <TextBlock Text="{Binding EntityName}" Foreground="White" ContextMenu="{StaticResource ContextMenuLevel1}"/>
                    </HierarchicalDataTemplate>
                    <DataTemplate DataType="{x:Type models:SlideModel}">
                        <StackPanel Orientation="Horizontal" ContextMenu="{StaticResource ContextMenuLevel2}">
                            <StackPanel.InputBindings>
                                <MouseBinding MouseAction="RightClick"
                                                    Command="{Binding ElementName=Emt,Path=DataContext.TreeViewRightClickCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=TreeViewItem}}"/>
                            </StackPanel.InputBindings>
                            <TextBlock Text="{Binding SlideName}" Foreground="White">
                                <TextBlock.InputBindings>
                                    <MouseBinding MouseAction="LeftDoubleClick"
                                                    Command="{Binding ElementName=Emt,Path=DataContext.SlideDoubleClickCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=TextBlock},Path=DataContext}"/>
                                </TextBlock.InputBindings>
                            </TextBlock>
                            <CheckBox IsChecked="{Binding IsChecked}" Foreground="White" />
                        </StackPanel>
                    </DataTemplate>
                </TreeView.Resources>
          </TreeView>
    

    And in the viewModel:

     private void ExecuteTreeViewRightClickCommand(object obj)
            {
                ((TreeViewItem)obj).IsSelected = true;
                SelectedSlide = ((TreeViewItem)obj).Header as SlideModel;
            }
    
    0 讨论(0)
  • 2021-01-13 09:28

    You could define a DependencyProperty. Below I have shared a sample app which uses a dependency property to achieve this.

    TreeViewExtension.cs

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    
    namespace WpfApplication1
    {
        public static class TreeViewExtension
        {
            public static readonly DependencyProperty SelectItemOnRightClickProperty = DependencyProperty.RegisterAttached(
               "SelectItemOnRightClick",
               typeof(bool),
               typeof(TreeViewExtension),
               new UIPropertyMetadata(false, OnSelectItemOnRightClickChanged));
    
            public static bool GetSelectItemOnRightClick(DependencyObject d)
            {
                return (bool)d.GetValue(SelectItemOnRightClickProperty);
            }
    
            public static void SetSelectItemOnRightClick(DependencyObject d, bool value)
            {
                d.SetValue(SelectItemOnRightClickProperty, value);
            }
    
            private static void OnSelectItemOnRightClickChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                bool selectItemOnRightClick = (bool)e.NewValue;
    
                TreeView treeView = d as TreeView;
                if (treeView != null)
                {
                    if (selectItemOnRightClick)
                        treeView.PreviewMouseRightButtonDown += OnPreviewMouseRightButtonDown;
                    else
                        treeView.PreviewMouseRightButtonDown -= OnPreviewMouseRightButtonDown;
                }
            }
    
            private static void OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
            {
                TreeViewItem treeViewItem = VisualUpwardSearch(e.OriginalSource as DependencyObject);
    
                if (treeViewItem != null)
                {
                    treeViewItem.Focus();
                    e.Handled = true;
                }
            }
    
            public static TreeViewItem VisualUpwardSearch(DependencyObject source)
            {
                while (source != null && !(source is TreeViewItem))
                    source = VisualTreeHelper.GetParent(source);
    
                return source as TreeViewItem;
            }
        }
    }
    

    XAML:

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:mvvmhelper="clr-namespace:WpfApplication1"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <TreeView mvvmhelper:TreeViewExtension.SelectItemOnRightClick="true">
                <TreeViewItem Header="One"/>
                <TreeViewItem Header="Two"/>
    
                <TreeViewItem Header="Three"/>
                <TreeView.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="Menu1"/>
                        <MenuItem Header="Menu2"/>
                    </ContextMenu>
                </TreeView.ContextMenu>
            </TreeView>
        </Grid>
    </Window>
    
    0 讨论(0)
提交回复
热议问题