.NET MenuItem.IsSubmenuOpen = true работает только в первый раз

У меня есть ContextMenu с некоторыми подменю, в которых есть элементы (MenuItem), которые можно выбрать. Когда ContextMenu открывается, я хочу рекурсивно открыть текущий выбранный элемент. Итак, у меня есть следующий код:

    protected override void OnOpened( RoutedEventArgs e ) {
        base.OnOpened( e );
        OpenCurrentSubMenu( Items );
    }

    private static bool OpenCurrentSubMenu( ItemCollection itemCollection ) {
        foreach (MenuItem item in itemCollection) {
            if (item.IsChecked) {
                return true;
            }
            else if( OpenCurrentSubMenu( item.Items ) ) {
                item.IsSubmenuOpen = true;
                return true;
            }
        }
        return false;
    }

У меня также есть другой код, который гарантирует, что проверяется только один элемент.

Кажется, это отлично работает, когда я впервые выбираю элемент в подменю. Когда я повторно открываю ContextMenu, каскад открытых подменю открывается для выбранного элемента:

Первое раскрывающееся меню

Однако, когда я выхожу из контекстного меню и снова открываю его во второй раз, выбранное меню НЕ открывается:

Следующее раскрывающееся меню

Кто-нибудь знает, почему и как это исправить?


person DiamondBack    schedule 23.11.2011    source источник
comment
Ваш заголовок говорит IsItemChecked, но ваш код говорит IsSubmenuOpen.   -  person Scott Rippey    schedule 23.11.2011
comment
@ScottRippey - Обновлено. Спасибо.   -  person DiamondBack    schedule 23.11.2011
comment
Вы можете проверить это с большим количеством уровней меню? Приводит ли каждое повторное открытие к повторному открытию на 1 уровень меньше или всегда просто не открывается финальное меню?   -  person Damien_The_Unbeliever    schedule 23.11.2011
comment
@Damien_The_Unbeliever - После некоторых экспериментов кажется, что первое открытие после выбора работает до n уровней. Но следующий и последующие Open открываются только до уровня 1.   -  person DiamondBack    schedule 23.11.2011


Ответы (3)


Три вещи, которые стоит попробовать:

  • Когда контекстное меню открыто, выполните рекурсию по всей иерархии и установите IsSubmenuOpen = false, прежде чем пытаться открыть какие-либо подменю. Возможно, ранее открытое подменю запоминается, и поэтому вы пытаетесь указать ему иметь два открытых подменю на одном уровне.

  • Recurse, чтобы найти подменю, которые необходимо открыть, и сохранить их в списке. Затем выполните итерацию по списку и установите их так, чтобы самое верхнее меню было открыто до открытия его дочернего подменю. (Возможно, попытка открыть дочерний элемент, когда его родитель еще не открыт, не всегда будет работать надежно).

  • Подход грубой силы: удаляйте и заново создавайте контекстное меню каждый раз, когда оно открывается. Это неприятно, но если вы открываете контекстное меню, вы, вероятно, будете беспокоиться о последствиях для производительности. И оказывается, что это работает с первого раза, так что делайте каждый раз с первого раза.

person Jason Williams    schedule 23.11.2011
comment
Хорошие советы. Я пробовал несколько вариантов: я попробовал метод Скотта Риппи. Я также пытался установить IsSubmenuOpen = false при закрытии, но безрезультатно. Ваша вторая пуля интересна, но не объясняет, почему каскад срабатывает в первый раз, а в последующие нет. Грубая сила всегда есть вариант :) - person DiamondBack; 23.11.2011
comment
Кажется, что второй вариант делает свое дело, хотя и не объясняет, почему каскад срабатывает с первого раза. !@*$# MS .NET - person DiamondBack; 23.11.2011
comment
Вполне вероятно, что некоторая информация не кэшируется при первой попытке, поэтому она работает в любом порядке, в котором вы устанавливаете меню, но при последующих попытках система меню знает больше об иерархии или состоянии существующих пунктов меню и, таким образом, сбивается с толку вашими попытками. изменить вещи. - person Jason Williams; 24.11.2011

Может помочь установить значение false, прежде чем снова установить его на true. Я не могу подтвердить это, хотя.

item.IsSubmenuOpen = false;
item.IsSubmenuOpen = true;
person Scott Rippey    schedule 23.11.2011
comment
Спасибо за подсказку, Скотт. Я видел подобные решения проблем .NET раньше, и это казалось многообещающим. К сожалению, в данном случае это не работает. - person DiamondBack; 23.11.2011

Я думаю, что логика должна работать хорошо ... когда отмечен пункт меню, но не когда отмечен пункт подменю. На мой взгляд, попробуйте два цикла.... один для меню, а другой для пунктов подменю.

person Naval    schedule 23.11.2011