WPF选择TreeView项作为上下文菜单称为

时间:2017-03-27 11:55:40

标签: c# wpf xaml treeview

此问题主要与上下文菜单有关,但在我的特定情况下,它与TreeView控件有关。

TreeView项包含一个StackPanel,在该StackPanel上是一个ContextMenu属性,我已将其分配给StaticResource(当然是ContextMenu)。所述ContextMenu导致ICommand,因此,它做了它的事情。

目前(这是我认为的默认行为),右键单击TreeView中的项目不会选择该项目。这在Windows中很常见,但这里不会发生。我希望它发生(但我不知道如何)。

一些跟进信息:我在TreeView中确实有一个选定的项目,只需用鼠标左键单击即可。但这不是左键单击事件,而是事件是'SelectedItemChanged'。这导致了一种方法,我将我的数据上下文(视图模型)中的'SelectedItem'设置为SelectedItem。它必须以这种方式完成,因为TreeView的所选项目是“只读”。

该代码在这里,虽然我不确定它对手头的问题有多大用处:

private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        if (this.ScenesTreeView01 == null)
            return;

        if (this.ScenesTreeView01.DataContext == null)
            return;

        var DataContext = this.ScenesTreeView01.DataContext as ScenesViewModel;

        if (e.NewValue is SceneViewModel)
        {
            DataContext.SelectedScene = (SceneViewModel)e.NewValue;
        }

        if (e.NewValue is CharacterViewModel)
        {

            DataContext.SelectedCharacter = (CharacterViewModel)e.NewValue;
        }
    }

由于似乎没有一个地方可以说'好吧你没有点击,所以这里是所选项目',我不知道怎么做告诉它在右键点击分配所选项目(以及左键单击)。

我该怎么做?

编辑:我正在使用MVVM,所以当我们有一个像SelectedItemChanged这样的方法,其参数是RoutedPropertyChangedEventArgs e时,e.Source会将我引回到我的视图模型,而不是TreeViewItem。

3 个答案:

答案 0 :(得分:1)

您可以向IsSelectedSceneViewModel类添加CharacterViewModel属性,并使用样式将IsSelected的{​​{1}}绑定到这些属性。在相同的样式中,您可以为TreeViewItem挂钩事件处理程序以设置源属性:

PreviewMouseRightButtonDown
<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; } } CharacterViewModel类实现SceneViewModel接口,并在新INotifyPropertyChanged属性的setter中引发PropertyChanged事件。< / p>

答案 1 :(得分:0)

快速解决方案可能只是注册TreeView的MouseRightButtonDown事件,检查点击是否在TreeViewItem上并选择它:

TreeView.MouseRightButtonDown += Tv_MouseRightButtonDown;

void Tv_MouseRightButtonDown(object sender, MouseButtonEventArgs e) {
    var tvItem = e.Source as TreeViewItem;
    if (tvItem != null) {
        tvItem.IsSelected = true;
    }
}

答案 2 :(得分:0)

您可以使用它的行为:

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();
    }
}

然后只将你的行为放到将被点击的元素上(我想在DataTemplate中有一个容器):

<StackPanel>
    <i:Interaction.Behaviors>
        <b:SelectOnRMBBehavior CurrentItem="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}}"/>
    </i:Interaction.Behaviors>
</StackPanel>