简体   繁体   中英

How can I prevent a WP7 context menu from closing after an item has been selected?

I have hooked up a context menu item in a listbox item such that tapping it will change its state. I need either the menu to stay open after the item has been selected, or to programmatically reopen the menu right after it closes.

My menu looks like so:

Some Command 1
Some Command 2
Some Command 3
Inverted

And the user can tap the Inverted command and then tap one of the other commands to cause them to function in Inverted Mode, and the menu through data binding appears like so:

Some Command 1
Some Command 2
Some Command 3
Inverted ✔ 

Not being able to figure out how to keep the menu open after tap, I've tried the less ideal reopen menu approach like so:

private void onCommandInvert(object sender, RoutedEventArgs e)
{
  CommandState.Instance.Inverted = !CommandState.Instance.Inverted;

  // Open it again.
  MenuItem menuItem = (MenuItem)sender;
  ContextMenu menu = (ContextMenu)menuItem.Parent;
  menu.IsOpen = true;
}

But doing so throws the following exception on the menu.IsOpen = true statement:

A first chance exception of type 'System.InvalidOperationException' occurred in 
  System.Windows.dll

An unhandled exception of type 'System.InvalidOperationException' occurred in 
  System.Windows.dll

Additional information: Element is already the child of another element.

I have also tried the following with the Closed event, with the same exception occurring:

private void onContextMenuClosed(object sender, RoutedEventArgs e)
{
  ContextMenu menu = (ContextMenu)sender;
  menu.IsOpen = true;
}

Any ideas? Thanks!

I got it! Thanks to willmel's comment, I digged through the source code for the MenuItem and was able to override OnClick() to do exactly what I needed (the ideal solution no doubt). I couldn't access Click however, so I needed to introduce a StayClick event property as well.

Enjoy!

using Microsoft.Phone.Controls;
using System.Windows;

namespace MyNamespace
{
  public class MenuItemEx : MenuItem
  {
    public bool StayOpenWhenClicked
    {
      get;
      set;
    }

    public event RoutedEventHandler StayClick;

    protected override void OnClick()
    {
      if (StayOpenWhenClicked)
      {
        if (StayClick != null)
        {
          StayClick.Invoke(this, new RoutedEventArgs());
        }
      }
      else
      {
        base.OnClick();
      }
    }
  }
}

and in the page's xaml, instead of toolkit:MenuItem you use my:MenuItemEx

<my:MenuItemEx 
  Header="Inverted"             
  StayClick="onCommandInvert"
  StayOpenWhenClicked="True"
/>

If you want to persist the menu after the user has selected an item then I believe the Context menu control is not what you should be using.

Better you should create your own user control to mimic the behaviour and have it place appropriately on the screen where it makes sense (to the side or above/below)

Alternatively if these are options to be enacted on selected items consider using the application bar icons / menu items and write the event code to read the currently selected value of the listbox item.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM