考虑一个在运行时可能没有完全用ListBoxItem填充的ListBox。我想为该ListBox自定义ContextMenu,具体取决于用户是右键单击其中一个ListBoxItem还是没有项目的空白区域。
我遇到的问题是,在后一种情况下,没有触发ListBox事件,只触发ContextMenuOpening事件。从那个事件我无法弄清楚如何确定用户是否右键单击现有的ListBoxItem。
我查看了所有ListBox属性和事件,但是canot提出了一种区分这两种情况的方法。我考虑使用样式触发器,但同样,核心问题是在空白处右键单击不会触发任何ListBox事件。我还审查了SO建议的链接,但没有人谈到这个问题。
如何做到这一点?
答案 0 :(得分:1)
这是一种更简洁的方法,可以为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
事件的处理程序,并在该处理程序中检查所选项目并添加新{{1}在代码中收集到MenuItem
。
请注意,这两个ContextMenu
只会在ContextMenu
内显示,因为它们是在ListBox
中定义的。
答案 1 :(得分:0)
我设计了一个不漂亮但有效的解决方案。基本上,每当ListBox失去焦点时,我强制它没有通过设置
选择任何内容ListBox.SelectedIndex = -1
现在,在ContextMenuOpening事件中,当焦点返回到ListBox时,可以获取ListBox.SelectedIndex,如果它是-1,则用户单击ListBox的空白部分,否则ListBoxItem是点击了。
编码这个逻辑非常简单。
答案 2 :(得分:0)
也许我没有达到您的意图:您可以在ContextMenu
或XAML
中定义不同的Code-behind
,如下所示:
XAML:
<ListBox PreviewMouseDown="ListBox_PreviewMouseDown">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter>
<ContentPresenter.ContextMenu>
<ContextMenu>
<MenuItem Header="ListBoxItem"></MenuItem>
<MenuItem Header="ListBoxItem"></MenuItem>
<MenuItem Header="ListBoxItem"></MenuItem>
</ContextMenu>
</ContentPresenter.ContextMenu>
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBoxItem>Item1</ListBoxItem>
<ListBoxItem>Item2</ListBoxItem>
<ListBoxItem>Item2</ListBoxItem>
<ListBoxItem>Item2</ListBoxItem>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="ListBox"></MenuItem>
<MenuItem Header="ListBox"></MenuItem>
<MenuItem Header="ListBox"></MenuItem>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
代码隐藏:
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
}
}
}