按钮上下文菜单未出现

Button ContextMenu not Appearing

我在按钮上有一个上下文菜单,我在 xaml 中添加如下:

<Button Content="{Binding MaterialLabel}"
        Command="{Binding SwapCommand}">
    <Button.Resources>
        <ContextMenu x:Key="RClickSwaps" ItemsSource="{Binding SwapList}">
            <ContextMenu.ItemContainerStyle>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Header" Value="{Binding targetMaterial.Component_Code}"/>
                    <Setter Property="Command" Value="{Binding RClickSwapCommand}"/>
                    <Setter Property="ToolTip">
                        <Setter.Value>
                            <ContentControl>
                                <Border CornerRadius="2" BorderThickness="2">
                                    <TextBlock Text="{Binding targetMaterial.Component_Name}"/>
                                </Border>
                            </ContentControl>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ContextMenu.ItemContainerStyle>
        </ContextMenu>
    </Button.Resources>
</Button>

UserControl 的绑定作为一个整体是到一个视图模型,其中包含 类 的集合(SwapList),其中包含命令和 TargetMaterial 属性对于上面使用的上下文菜单:

//Control View Model
public ObservableCollection<SwapMenuItem> SwapList { get; set; }

//... Some irrelevant Code excluded ...

SwapList = new ObservableCollection<SwapMenuItem>();
var swaps = new ObservableCollection<Raw_Materials>(await ComponentDataService.GET_MaterialSwaps(New_Material));
foreach (var item in swaps)
{
    SwapList.Add(new SwapMenuItem(item, this));
}
OnPropertyChanged("SwapList");

SwapMenuItem 本身包含以下属性和看起来有点像这样的命令:

public class SwapMenuItem : Observable
{
    public ComponentChangeViewModel ComponentChangeViewModel { get; set; }
    public Raw_Materials TargetMaterial { get; set; }
    public ICommand RClickSwapCommand {get;set;}

    public SwapMenuItem(Raw_Materials raw_Materials, ComponentChangeViewModel componentChangeViewModel)
    {
        ComponentChangeViewModel = componentChangeViewModel;
        TargetMaterial = raw_Materials;
    }

    private void Swap()
    {
        //The command actually calls this method, but I excluded the long winded code
    }
}

我的问题是右键单击按钮时没有出现上下文菜单,根本没有任何反应。我正在尝试在 MVVM 模式下工作,但我是否缺少某种事件来使上下文菜单出现在右键单击时?大多数在线建议不使用上下文菜单作为 Button.Resources 的一部分,但根据一些 (for instance here) 这似乎是最好的方法。 None 这些示例包含使上下文菜单在右键单击时出现的任何内容,所以我认为它必须默认存在?

为什么即使 ItemsSource 集合中有值,我也无法显示上下文菜单?

您只在资源中定义一个带有键的上下文菜单。 Button 不会自动知道它应该使用它。您必须将此资源设置为 Button.

ContextMenu 属性

您可以在元素 属性 语法中使用 StaticResource 标记扩展,如下所示:

<Button Content="{Binding MaterialLabel}"
        Command="{Binding SwapCommand}">
    <Button.Resources>
        <ContextMenu x:Key="RClickSwaps" ItemsSource="{Binding SwapList}">
            <!-- ...your context menu markup. -->
        </ContextMenu>
    </Button.Resources>
    <Button.ContextMenu>
       <StaticResource ResourceKey="RClickSwaps"/>
    </Button.ContextMenu>
</Button>

或者您可以使用 DynamicResource 标记扩展在属性语法中设置它。请注意,StaticResource 在这里不起作用,因为资源 RClickSwaps 稍后在 XAML 中定义,因此此时无法静态解析。

<Button Content="{Binding MaterialLabel}"
        Command="{Binding SwapCommand}"
        ContextMenu="{DynamicResource RClickSwaps}">
    <Button.Resources>
        <ContextMenu x:Key="RClickSwaps" ItemsSource="{Binding SwapList}">
            <!-- ...your context menu markup. -->
        </ContextMenu>
    </Button.Resources>
</Button>

当然你也可以直接指定上下文菜单,不用Resources

<Button Content="{Binding MaterialLabel}"
        Command="{Binding SwapCommand}">
   <Button.ContextMenu>
      <ContextMenu ItemsSource="{Binding StringItems}">
         <!-- ...your context menu markup. -->
      </ContextMenu>
   </Button.ContextMenu>
</Button>