Disable Right click and enable left click for contextmenu in WPF using MVVM
Code:
<Button Style="{StaticResource HPForegroundStyle}" IsTabStop="False"
Command="{Binding ForegroundPhoneCommand}" Click="Button_Click">
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding OptionsMenuItemList}" ItemContainerStyle="{StaticResource ContextMenuItemStyle}"
开发者_Python百科 IsOpen="{Binding IsMenuOpen}"
PlacementTarget="{Binding RelativeSourc={RelativeSource AncestorType={x:Type Button}}}">
</ContextMenu>
</Button.ContextMenu>
</Button>
i am using MVVM pattern. In ViewModel i have a property 'IsMenuOpen' which controls context menu open close .Problem is that i'm able to disable right click and not able to show context menu on left click.
You can check also ContextMenuService.IsEnabled
attached property on the parent control. It will block only right click and you will still be able to show the menu manually on left click, so based on previous example:
<Button x:Name="btn" Click="btn_Click" ContextMenuService.IsEnabled="false">
<Button.ContextMenu>
<ContextMenu x:Name="popup">
...
</ContextMenu>
</Button.ContextMenu>
</Button>
private void btn_Click(object sender, RoutedEventArgs e)
{
popup.Visibility = Visibility.Visible;
popup.IsOpen = true;
}
This worked for me using XAML similar to the question.
private bool _isMenuOpen = false;
public bool IsMenuOpen
{
get { return _isMenuOpen; }
set
{
// Don't allow the UI (right-click) to set this property to true
if (!value)
_isMenuOpen = value;
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
_isMenuOpen = true;
btn.ContextMenu.IsOpen = true;
}
A few things to keep track of:
- Ensure that the DataContext of the ContextMenu is valid.
- Make sure that IsOpen is a TwoWay binding.
- If you're going to attempt left click opening, remember that the PlacementTarget is not valid, so you'll have to set Button.ContextMenu.PlacementTarget = this, and then IsMenuOpen = true to have it show up.
My code snippet for reference:
<Style x:Key="SubjectButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource CommandButtonStyle}">
<Setter Property="Foreground" Value="Green" />
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu DataContext="{Binding PlacementTarget.DataContext.Manager, RelativeSource={RelativeSource Self}}"
ItemsSource="{Binding SubjectManager.ContextMenuItems}"
IsOpen="{Binding SubjectManager.ContextMenuIsOpen, Mode=TwoWay}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding OnClick}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="DarkGreen" />
</Trigger>
</Style.Triggers>
</Style>
And in the view model:
public void ShowContextMenu(SearchCondition searchCondition, Button button)
{
button.ContextMenu.DataContext = this;
SubjectManager.OpenContextMenu();
}
If you want to bind a menu to a property, consider the Popup control. It has similar functionality to the context menu but is not bound to a particular mouse button...
<Popup IsVisible = {Binding IsMenuOpen} >
<!-- Fill in what you need here -->
</Popup>
You can do it just like that:
<Button x:Name="btn" Click="btn_Click" MouseRightButtonDown="btn_MouseRightButtonDown">
<Button.ContextMenu>
<ContextMenu x:Name="popup" Visibility="Collapsed">
<MenuItem Header="aaa"></MenuItem>
<MenuItem Header="bbb"></MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button>
private void btn_Click(object sender, RoutedEventArgs e)
{
popup.Visibility = Visibility.Visible;
popup.IsOpen = true;
}
private void btn_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
popup.Visibility = Visibility.Collapsed;
}
精彩评论