在WPF中使用MVVM模式禁用右键点击并启用左键点击以显示上下文菜单

6

代码:

<Button Style="{StaticResource HPForegroundStyle}" IsTabStop="False"                 
        Command="{Binding ForegroundPhoneCommand}"  Click="Button_Click">
                    <Button.ContextMenu>                   
                        <ContextMenu ItemsSource="{Binding OptionsMenuItemList}"                            ItemContainerStyle="{StaticResource ContextMenuItemStyle}" 
                                     IsOpen="{Binding IsMenuOpen}"                                        
                                     PlacementTarget="{Binding RelativeSourc={RelativeSource AncestorType={x:Type Button}}}">
                        </ContextMenu>
                    </Button.ContextMenu>
    </Button>

我正在使用MVVM模式。在ViewModel中,我有一个名为 'IsMenuOpen' 的属性,它控制上下文菜单的打开和关闭。问题是,我能够禁用右键单击,但无法在左键单击时显示上下文菜单。


你是如何打开上下文菜单的?是弹出式菜单还是实际的上下文菜单控件? - TerrorAustralis
当你右键点击时,它不会打开,但左键点击也无法打开吗?ForegroundPhoneCommand是否导致IsMenuOpen属性设置为true?IsMenuOpen属性是否实现了INotifyPropertyChanged接口? - TerrorAustralis
请查看 AttachedCommandBehavior。它可能会对您有所帮助... - TerrorAustralis
ForegroundPhoneCommand将IsMenuOpen属性设置为true,并实现了INotifyPropertyChange。 - suman
它的绑定正确,我能够通过右键单击打开上下文菜单。 - suman
显示剩余2条评论
5个回答

22

您还可以检查父控件上的 ContextMenuService.IsEnabled 附加属性。 它将仅阻止右键单击,您仍然可以在左键单击时手动显示菜单,因此基于先前的示例:

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

1
严肃地说,这根本就不起作用...我的上下文菜单仍然会出现并立即消失。 - user1034912

2

我使用类似于问题中的XAML,这对我起了作用。

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

2

需要注意的几点:

  1. 确保ContextMenu的DataContext有效。
  2. 确保IsOpen是双向绑定。
  3. 如果您要尝试使用左键打开,请记住PlacementTarget无效,因此您需要设置Button.ContextMenu.PlacementTarget = this,然后将IsMenuOpen = true以使其显示。

我的代码片段供参考:

<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>

在视图模型中:

public void ShowContextMenu(SearchCondition searchCondition, Button button)
{
    button.ContextMenu.DataContext = this;
    SubjectManager.OpenContextMenu();
}

0
如果您想将菜单绑定到属性,请考虑使用 Popup 控件。它具有类似于上下文菜单的功能,但不绑定到特定的鼠标按钮...
<Popup IsVisible = {Binding IsMenuOpen} >
    <!-- Fill in what you need here -->
</Popup>

0

你可以像这样做:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接