我有一个ContextMenu
ItemsSource
绑定到列表视图的选定项目,如下所示:
<ContextMenu ItemsSource="{Binding Path=PlacementTarget.SelectedItem,
RelativeSource={RelativeSource Self}, Converter={StaticResource possibleConverter}}"/>
possibleConverter
枚举所选项的属性的所有可能值,这些值显示在上下文菜单中。在上下文菜单的Opened
事件中,我选择了这样的当前值:
var cm = e.OriginalSource as ContextMenu;
if (cm != null) {
var lv = cm.PlacementTarget as ListView;
var field = lv.SelectedItem as Field;
var item = cm.ItemContainerGenerator.ContainerFromItem(cm.Items.OfType<object>().Where(o => o.ToString().Equals(field.StringValue)).FirstOrDefault()) as MenuItem;
if (item != null) {
item.IsChecked = true;
}
}
不是特别优雅,但它有效。使用调试器,我验证了ContextMenu.Items.Count
属性在预期时具有非零值(即cm.Items.Count
在if中为非零。
到目前为止,这么好。但是,列表视图中的项目上下文菜单中没有项目。在这种情况下,会显示一个空菜单。我试图在列表视图中的ContextMenuOpening
事件中禁止这样做,如下所示:
var lv = sender as ListView;
if (lv != null) {
var cm = lv.ContextMenu;
if ((cm != null) && (cm.Items.Count > 0)) {
// Here we want to check the current item, which is currently done in the Opened event.
} else {
e.Handled = true;
}
}
似乎它应该工作。但是,cm.Items.Count
始终为零。即使ListView.SelectedItem
没有改变也是如此:对于带有菜单条目的项目,第一次单击后菜单会正确显示,因此数据绑定已经发生。第二次显示正确,但无论如何,Items.Count
事件中ContextMenuOpening
为零。
我错过了什么?如何禁止空上下文菜单?为什么ContextMenuOpening
处理程序中的计数为零(在Windows窗体(ContextMenuStrip.Opening
中)是规范点,在哪里执行这些操作?
编辑:经过进一步调查,结果发现在ContextMenuOpening
处理程序中,对listview的任何绑定都失败了,这就是ItemsSource为空的原因。我尝试通过ElementName
通过FindAncestor
关系进行绑定,但都无济于事。在该事件期间PlacementTarget
为空。一个丑陋的黑客工作:在ContextMenuOpening
事件中,我将列表视图分配给ContextMenu.Tag
属性,而ItemsSource
绑定现在绑定到Tag.SelectedItem
。这会更新绑定,因此Items.Count
应该是它。它仍然很奇怪。如果绑定失败,你怎么能在ContextMenuOpening
中做有意义的事情,如果绑定失败,因为某些情况下上下文菜单在事件期间脱离了上下文?它是否仅使用静态预定义菜单项进行测试?