У меня есть 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 Forms (ContextMenuStrip.Opening
) является канонической точкой, где делать эти вещи?
РЕДАКТИРОВАТЬ: После дальнейшего исследования выясняется, что в обработчике ContextMenuOpening
любая привязка к просмотру списка не выполняется, поэтому ItemsSource имеет значение null. Я пытался связать через ElementName
, через FindAncestor
отношения, все безрезультатно. PlacementTarget
является нулевым во время этого события. Хотя уродливый хак сработал: в событии ContextMenuOpening
я назначаю представление списка свойству ContextMenu.Tag
, в то время как привязка ItemsSource
теперь привязывается к Tag.SelectedItem
. Это обновляет привязку, поэтому Items.Count
так и должно быть. Это все еще странно. Как вы можете сделать значимые вещи в ContextMenuOpening
, кроме замены меню или чего-то еще, если привязка не удалась, потому что контекстное меню каким-то образом вышло из контекста во время события? Было ли оно протестировано только со статическими предопределенными пунктами меню?