I have a ContextMenu
with the ItemsSource
bound to the selected item of a list view, like this:
<ContextMenu ItemsSource="{Binding Path=PlacementTarget.SelectedItem,
RelativeSource={RelativeSource Self}, Converter={StaticResource possibleConverter}}"/>
The possibleConverter
enumerates all possible values for a property of the the selected item, which are shown in the context menu. In the Opened
event of the context menu, I select the current value like this:
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;
}
}
Not particularly elegant, but it works. With the debugger I verified that the ContextMenu.Items.Count
property has a non-zero value when expected (i.e. cm.Items.Count
is non-zero in the if).
So far, so good. There are, however, items in the listview where the context menu will have no items. In this case, an empty menu is shown. I tried to suppress this in the ContextMenuOpening
event in the list view, like this:
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;
}
}
Seems like it should work. However, cm.Items.Count
is always zero. This is true even if ListView.SelectedItem
did not change: For an item with menu entries, the menu is shown correctly after the first click, so the data binding has already happend. It is shown correct the second time as well, but in any case, Items.Count
is zero in the ContextMenuOpening
event.
What am I missing? How can I suppress empty context menus? Why is the count zero in the ContextMenuOpening
handler, which is in Windows Forms (ContextMenuStrip.Opening
) the canonical point where to do these things?
EDIT: Upon further investigating, it turns out that in the ContextMenuOpening
handler, any binding to the listview fails, which is why ItemsSource is null. I tried to bind via ElementName
, via a FindAncestor
relationship, all to no avail. The PlacementTarget
is null during that event. An ugly hack worked though: In the ContextMenuOpening
event, I assign the list view to the ContextMenu.Tag
property, while the ItemsSource
binding now binds to Tag.SelectedItem
. This updates the binding, so Items.Count
is what it should be. It's still strange. How can you do meaningful things in ContextMenuOpening
other than replacing the menu or something, if the binding fails because somehow the context menu is out of context during the event? Was it only tested with static pre-defined menu items?