如何自定义wpf列表框的上下文菜单

如何自定义wpf列表框的上下文菜单,wpf,listbox,contextmenu,Wpf,Listbox,Contextmenu,考虑一个在运行时可能没有完全填充ListBoxItems的ListBox。我想根据用户右键点击一个ListBox项目或在没有项目存在的空白空间来定制该列表框的上下文菜单。 我遇到的问题是,在后一种情况下,没有激发ListBox事件,只有ContextMenuOpening事件被激发。从那个事件中,我无法确定用户是否右键单击了现有的ListBoxItem 我已经查看了所有的ListBox属性和事件,但是没有找到一种方法来区分这两种情况。我已经考虑过使用样式触发器,但同样,核心问题是空白空间中的右击

考虑一个在运行时可能没有完全填充ListBoxItems的ListBox。我想根据用户右键点击一个ListBox项目或在没有项目存在的空白空间来定制该列表框的上下文菜单。

我遇到的问题是,在后一种情况下,没有激发ListBox事件,只有ContextMenuOpening事件被激发。从那个事件中,我无法确定用户是否右键单击了现有的ListBoxItem

我已经查看了所有的ListBox属性和事件,但是没有找到一种方法来区分这两种情况。我已经考虑过使用样式触发器,但同样,核心问题是空白空间中的右击不会触发任何列表框事件。我也回顾了这些建议的链接,但没有一个提到这个问题


如何做到这一点?

我设计了一个解决方案,虽然不美观,但确实有效。基本上,每当ListBox失去焦点时,我通过设置强制它不选择任何内容

ListBox.SelectedIndex = -1

现在,在焦点返回到ListBox的上下文菜单打开事件中,可以获得get ListBox .SeldDead,如果是-1,那么用户点击列表框的空白部分,否则点击ListBox项目。< /P>


编写此逻辑很简单。

也许我没有理解您的意图:您可以在
XAML
代码隐藏中定义不同的
ContextMenu
,如下所示:

XAML:


这里有一种更简洁的方法来定义两个不同的
ContextMenu
,用于
ListBox
及其
ListBoxItem
,无需任何代码隐藏检查,它就像一个符咒:

<ListBox ContextMenu="{StaticResource ListContextMenu}">
    <ListBox.Resources>
        <!-- Context Menu when right click on selected List Item -->
        <ContextMenu x:Key="ItemContextMenu">
            <MenuItem Header="Eat"></MenuItem>
            <MenuItem Header="Delete"></MenuItem>
            <Separator></Separator>
            <MenuItem Header="Send To Friend"></MenuItem>
        </ContextMenu>
        <!-- Context Menu when right click on listbox space -->
        <ContextMenu x:Key="ListContextMenu">
            <MenuItem Header="Save Fruits"></MenuItem>
            <MenuItem Header="Add Or Remove Fruits"></MenuItem>
        </ContextMenu>
        <!-- Applying Context Menu to ListBoxItem with Style -->
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}">
            </Setter>
        </Style>
    </ListBox.Resources>

    <ListBox.ContextMenu>
        <Binding Source="{StaticResource ListContextMenu}"></Binding>
    </ListBox.ContextMenu>


    <ListBoxItem>Banana</ListBoxItem>
    <ListBoxItem>Apple</ListBoxItem>
    <ListBoxItem>Orange</ListBoxItem>
</ListBox>

香蕉
苹果
橙色
如果要根据所选项目动态修改
ListBoxItem.ContextMenu
的内容,可以为
ContextMenu.Opened
事件连接一个处理程序,并在该处理程序中检查所选项目,并将新的
MenuItem
集合添加到代码中的
ContextMenu


请注意,这两个
上下文菜单
将仅显示在此
列表框
中,因为它们是在其
列表框中定义的。参考资料

能否提供一些代码来更清楚地解释您的问题?能否显示您使用的逻辑以及您的逻辑连接到的事件?您可以在参考资料中创建两个ContextMenu,并在ListBox.ContextMenu和ListBoxItem.ContextMenu中使用它们。@Iron这不是一个编码问题,而是一个概念性问题:如何检测在部分填充的ListBox中单击鼠标右键的内容。如果我有任何代码,我会显示它。但请看下面我的解决方案。@Redouane请看上面我的注释。
private void ListBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    if(e.ChangedButton == MouseButton.Right)
    {
        var listBoxItem = e.Source as ListBoxItem;
        if (listBoxItem != null)
        {
            // clicked on ListBoxItem, customize the ContextMenu
        }

        var listBox = e.Source as ListBox;
        if (listBox != null)
        {
            // clicked on ListBox, customize the ContextMenu
        }
    }
}
<ListBox ContextMenu="{StaticResource ListContextMenu}">
    <ListBox.Resources>
        <!-- Context Menu when right click on selected List Item -->
        <ContextMenu x:Key="ItemContextMenu">
            <MenuItem Header="Eat"></MenuItem>
            <MenuItem Header="Delete"></MenuItem>
            <Separator></Separator>
            <MenuItem Header="Send To Friend"></MenuItem>
        </ContextMenu>
        <!-- Context Menu when right click on listbox space -->
        <ContextMenu x:Key="ListContextMenu">
            <MenuItem Header="Save Fruits"></MenuItem>
            <MenuItem Header="Add Or Remove Fruits"></MenuItem>
        </ContextMenu>
        <!-- Applying Context Menu to ListBoxItem with Style -->
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}">
            </Setter>
        </Style>
    </ListBox.Resources>

    <ListBox.ContextMenu>
        <Binding Source="{StaticResource ListContextMenu}"></Binding>
    </ListBox.ContextMenu>


    <ListBoxItem>Banana</ListBoxItem>
    <ListBoxItem>Apple</ListBoxItem>
    <ListBoxItem>Orange</ListBoxItem>
</ListBox>