In Windows Phone there is a feature called ContextMenu, which allows to create a popup menu for controls.
However, if the list of menu items is quite big, some of them doesn't fit the screen. The following simple example will show the point:
in xaml:
We will be using Toolkit, so adding
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
and then for example:
<Button Content="Button 1" Height="72" HorizontalAlignment="Left" Margin="160,400,0,0" Name="button1" VerticalAlignment="Top" Width="160">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Action A" Name="miActionA1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />
<toolkit:MenuItem Header="Action B" Name="miActionB1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />
<toolkit:MenuItem Header="Action C" Name="miActionC1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />
<toolkit:MenuItem Header="Action D" Name="miActionD1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />
<toolkit:MenuItem Header="Action E" Name="miActionE1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />
<toolkit:MenuItem Header="Action F" Name="miActionF1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</Button>
At nullAction we're doing nothing
private void nullAction(object sender, RoutedEventArgs e)
{
}
The DesignHeight value is standard for the default WP7 page it's DesignHeight="768"
As you can see, when you long tap the "Button 1" control, the menu is shown, but not completely. Some items are not visible. In my case, the best decision was to make this menu scrollable. That can be done, using ScrollViewer.
So, we cover the menu items with Scrollviewer and StackPanel.
<Button Content="Button 1" Height="72" HorizontalAlignment="Left" Margin="160,400,0,0" Name="button1" VerticalAlignment="Top" Width="160">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<ScrollViewer>
<StackPanel>
<toolkit:MenuItem Header="Action A" Name="miActionA1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />
<toolkit:MenuItem Header="Action B" Name="miActionB1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />
<toolkit:MenuItem Header="Action C" Name="miActionC1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />
<toolkit:MenuItem Header="Action D" Name="miActionD1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />
<toolkit:MenuItem Header="Action E" Name="miActionE1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />
<toolkit:MenuItem Header="Action F" Name="miActionF1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />
</StackPanel>
</ScrollViewer>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</Button>
Success? Nope, because you can scroll this list, but can't choose the item down.
My question, is how to fix it?
Use multitouch? (I don't know much about it)
Perhaps, I need to add some property to Scrolviewer?
Any other ideas?
[updated] Also, found that tap/click handlers for items change behavior, if scrollviewer is added. Normally, when you tap the item, the context menu closes and the handler method executes. With scrollviewer, the context menu doesn't close, needs one more tap to close it manually. Why's that happening?
If the native ContextMenu doesn't allow this, then, the best way to solve a problem, is to write your own implementation.
The new context menu should be shown in a popup with a choice of several items, and that items must be scrollable. So:
The ScrollableContextMenuItem is a UserControl, which should look like native ContextMenuItem. In short, it's a simple TextBox over Grid/StackPanel.
The native ContextMenu is added to the xaml file as
Instead, the ScrollableContextMenu object should be called via Hold event:
Where the defined list is a List of headers for context menu (should be generated somewhere).
At listBoxTap event:
That's the only solution, that really helped me. Hope it'll help someone else.