WPF selection of a TreeView item as context menu is called

前端 未结 3 1364
别那么骄傲
别那么骄傲 2020-12-21 11:06

This problem relates mainly to context menus, but in my specific case it\'s about a TreeView control.

The TreeView item contains a StackPanel, and on that StackPanel

相关标签:
3条回答
  • 2020-12-21 11:28

    You can use a behavior for it:

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Interactivity;
    
    public class SelectOnRMBBehavior : Behavior<FrameworkElement>
    {
        public static readonly DependencyProperty CurrentItemProperty = DependencyProperty.Register("CurrentItem", typeof(TreeViewItem), typeof(SelectOnRMBBehavior), new PropertyMetadata(null));
    
        public TreeViewItem CurrentItem
        {
            get
            {
                return (TreeViewItem)GetValue(CurrentItemProperty);
            }
            set
            {
                SetValue(CurrentItemProperty, value);
            }
        }
    
        protected override void OnAttached()
        {
            base.OnAttached();
    
            AssociatedObject.PreviewMouseRightButtonDown += AssociatedObject_PreviewMouseRightButtonDown;
        }
    
        private void AssociatedObject_PreviewMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (CurrentItem!=null)
            {
                CurrentItem.IsSelected = true;
            }
        }
    
        protected override void OnDetaching()
        {
            AssociatedObject.PreviewMouseRightButtonDown -= AssociatedObject_PreviewMouseRightButtonDown;
    
            base.OnDetaching();
        }
    }
    

    and then just put your behavior to the element which will be clicked(I suppose a container in DataTemplate):

    <StackPanel>
        <i:Interaction.Behaviors>
            <b:SelectOnRMBBehavior CurrentItem="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}}"/>
        </i:Interaction.Behaviors>
    </StackPanel>
    
    0 讨论(0)
  • 2020-12-21 11:31

    A quick solution might be to simply register the TreeView's MouseRightButtonDown event, check if the click was on a TreeViewItem and select it:

    TreeView.MouseRightButtonDown += Tv_MouseRightButtonDown;
    
    void Tv_MouseRightButtonDown(object sender, MouseButtonEventArgs e) {
        var tvItem = e.Source as TreeViewItem;
        if (tvItem != null) {
            tvItem.IsSelected = true;
        }
    }
    
    0 讨论(0)
  • 2020-12-21 11:48

    You could add an IsSelected property to your SceneViewModel and CharacterViewModel classes and bind the IsSelected of the TreeViewItem to these properties using a style. In the same style you could then hook up an event handler for the PreviewMouseRightButtonDown to set the source property:

    <TreeView x:Name="treeView">
        <TreeView.Resources>
            <Style TargetType="TreeViewItem">
                <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                <EventSetter Event="PreviewMouseRightButtonDown" Handler="treeView_PreviewMouseRightButtonDown" />
                <Setter Property="ContextMenu">
                    <Setter.Value>
                        <ContextMenu>
                            <MenuItem>1</MenuItem>
                        </ContextMenu>
                    </Setter.Value>
                </Setter>
            </Style>
        </TreeView.Resources>
    </TreeView>
    

    private void treeView_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
    {
        TreeViewItem tvi = sender as TreeViewItem;
        CharacterViewModel cvm = tvi.DataContext as CharacterViewModel;
        if (cvm != null)
        {
            cvm.IsSelected = true;
        }
        else
        {
            SceneViewModel svm = tvi.DataContext as SceneViewModel;
            if (svm != null)
                svm.IsSelected = true;
        }
    }
    

    Make sure that the CharacterViewModel and SceneViewModel classes implement the INotifyPropertyChanged interface and raise the PropertyChanged event in the setter of the new IsSelected property.

    0 讨论(0)
提交回复
热议问题