此问题主要与上下文菜单有关,但在我的特定情况下,它与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。
答案 0 :(得分:1)
您可以向IsSelected
和SceneViewModel
类添加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>