12

I need to open up a menu and since WP7 is not designed to perform such actions, I am taking help of Toolkit. Following is the sample code:

<Border BorderThickness="3" Padding="6">
     <toolkit:ContextMenuService.ContextMenu>
         <toolkit:ContextMenu>
             <toolkit:MenuItem Header="item1" Click="Item1_Click" />
             <toolkit:MenuItem Header="item2" Click="Item2_Click" />
             <toolkit:MenuItem Header="item3" Click="Item3_Click" />
         </toolkit:ContextMenu>
     </toolkit:ContextMenuService.ContextMenu>
     <TextBlock Text="Tap" />
</Border>

Now this works fine as long as user does a press and hold action. But I can't ask the user for such action. I need to display the menu on a single click/tap/touch/gesture (watever you want to call it). Can someone please suggest? If you think toolkit is not the best way, then please suggest alternatives with sample code. I tried popup but that did more bad than good to my applicaiton

Ravi
  • 147
  • 1
  • 10

2 Answers2

14

You could add GestureListener to the Border and subscribe to the Tap event. In the event handler, you get the ContextMenu for the Border and set IsOpen to true if it doesn't have a logical parent.

<Border BorderThickness="3" Padding="6">
    <toolkit:GestureService.GestureListener>
        <toolkit:GestureListener Tap="GestureListener_Tap" />
    </toolkit:GestureService.GestureListener>
    <toolkit:ContextMenuService.ContextMenu>
        <toolkit:ContextMenu>
            <toolkit:MenuItem Header="item1" Click="Item1_Click" />
            <toolkit:MenuItem Header="item2" Click="Item2_Click" />
            <toolkit:MenuItem Header="item3" Click="Item3_Click" />
        </toolkit:ContextMenu>
    </toolkit:ContextMenuService.ContextMenu>
    <TextBlock Text="Tap" />
</Border>

private void GestureListener_Tap(object sender, GestureEventArgs e)
{
    Border border = sender as Border;
    ContextMenu contextMenu = ContextMenuService.GetContextMenu(border);
    if (contextMenu.Parent == null)
    {
        contextMenu.IsOpen = true;
    }
}
Fredrik Hedblad
  • 83,499
  • 23
  • 264
  • 266
  • That does the job. On a side note. Any idea on how to highlight the selected option. I want to just highlight the selected row with row background color set to gray or something – Ravi Feb 06 '11 at 21:25
  • 1
    @Ravi: Do you have to highlight the selected `MenuItem` based on some condition prior to opening the `ContextMenu`? Maybe try to name the `MenuItem` s and set `menuItem1.Background = new SolidColorBrush(Colors.Gray);` based on the condition – Fredrik Hedblad Feb 07 '11 at 06:36
  • awesome ... thanks ... i didn't try it on the menuitem but used elsewhere and works like a charm. – Ravi Feb 08 '11 at 15:23
  • 1
    hi, there seems to be a problem with this solution, when I first start my application and tap on the text box the context menu is at the top of the screen: http://i.stack.imgur.com/ekOOI.png When I switch the page in my pivot navigation the context menu changes in position: http://i.stack.imgur.com/0L0Hb.png Any ideas how to solve this? – DarkLeafyGreen Apr 01 '12 at 22:29
0

If you want a context menu for your application, then the ContextMenu and ContextMenuService are the best approach to take because it is standard throughout third party and pre-installed applications. Users already understand the 'tap-and-hold' gesture, so working around that will be counter-intuitive.

If (for whatever reason) you must initiate a ContextMenu from a single tap, then you can always customize the source code for ContextMenu.cs from the Silverlight Toolkit so that instead of hooking the Hold event it hooks the Tap event.

Derek Lakin
  • 16,179
  • 36
  • 51
  • Hi Derek, that didn't help much. Considering the fact that I am pretty new to WP7 and silverlight, I checked the surce code but didn't understand much. Can you please help me in changing the tap and hold action to just tap? – Ravi Feb 06 '11 at 15:25
  • Download the source code for Silverlight Toolkit, open the source file I referenced, change the `.Hold += ` to `.Tap +=`, recompile, update the reference in your projec to the new assembly. I still doubt very much changing default behavior is the right way to go, though. – Derek Lakin Feb 06 '11 at 19:05
  • Hi Derek, you are probably right. I should go with the suggestion of Meleak and use gesture service. Thanks anyways – Ravi Feb 06 '11 at 21:24