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