在Windows Phone中,有一项名为 ContextMenu 的功能,可以为控件创建一个弹出菜单。
但是,如果菜单项列表很大,其中一些不适合屏幕。以下简单示例将说明要点:
xaml中的:
我们将使用Toolkit,因此添加
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
然后例如:
<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>
在nullAction,我们什么都不做
private void nullAction(object sender, RoutedEventArgs e)
{
}
DesignHeight值是默认WP7页面的标准值DesignHeight="768"
如您所见,当您长按“按钮1”控件时,会显示菜单,但不会完全显示。一些项目 不可见。在我的情况下,最好的决定是使这个菜单可滚动。可以使用 ScrollViewer 。
完成因此,我们使用Scrollviewer和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>
成功?不,因为你可以滚动这个列表,但是 无法选择该项目。
我的问题是,如何修复它?
使用多点触控? (我不太了解它)
也许,我需要向Scrolviewer添加一些属性吗?
还有其他想法吗?
[已更新] 此外,如果添加了scrollviewer,则会发现项目的点击/点击处理程序会更改行为。通常,当您点击该项时,上下文菜单关闭并执行处理程序方法。使用scrollviewer,上下文菜单不会关闭,需要再次点击以手动关闭它。为什么会这样?
答案 0 :(得分:0)
如果本机ContextMenu不允许这样做,那么解决问题的最佳方法是编写自己的实现。
新的上下文菜单应该显示在弹出窗口中,并且可以选择多个项目,并且这些项目必须是可滚动的。所以:
public class ScrollableContextMenu
{
private Popup p;
public delegate void TapHandler(object sender, System.Windows.Input.GestureEventArgs e);
public event TapHandler ListBoxTap;
private ListBox listBox;
public ListBox ListBox
{
get { return listBox; }
set { listBox = value; }
}
/// <summary>
/// Create new Context Menu. The items of Context Menu will be taken from given list
/// </summary>
/// <param name="page"></param>
/// <param name="items"></param>
public ScrollableContextMenu(PhoneApplicationPage page, List<string> items)
{
p = new Popup();
// Generate popup properties, i.e. height, width, e.t.c.
Canvas canvas = new Canvas();
// Generate canvas main properties
p.Child = canvas;
Border border = new Border();
// Now create border and its main properties
canvas.Children.Add(border);
// StackPanel.
StackPanel panel = new StackPanel();
panel.Orientation = System.Windows.Controls.Orientation.Vertical;
// Create listBox, that we will be scrolling
listBox = new ListBox();
// Create listbox main properties
// Fill the listbox with items.
foreach (string item in items)
listBox.Items.Add(new ScrollableContextMenuItem(item));
listBox.Tap += listBoxTap;
panel.Children.Add(listBox);
border.Child = panel;
}
public void Show()
{
// Open the popup.
p.IsOpen = true;
p.UpdateLayout();
}
public void Close()
{
// Close it
p.IsOpen = false;
p.UpdateLayout();
}
private void listBoxTap(object sender, System.Windows.Input.GestureEventArgs e)
{
// Invoke hanlder if it exists
if (ListBoxTap != null)
ListBoxTap(sender, e);
}
ScrollableContextMenuItem 是一个UserControl,应该看起来像本机ContextMenuItem。简而言之,它是一个简单的TextBox over Grid / StackPanel。
本机ContextMenu作为
添加到xaml文件中<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="..." ... Click="miClickEvent"/>
<!-- ... --!>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
相反,应通过Hold事件调用ScrollableContextMenu对象:
button.Hold += new EventHandler<System.Windows.Input.GestureEventArgs>(SomeHoldEvent);
private void SomeHoldEvent(object sender, EventArgs e)
{
contextMenu = new ScrollableContextMenu(this, definedList);
contextMenu.ListBoxTap +=new ScrollableContextMenu.TapHandler(contextMenu_ListBoxTap);
contextMenu.Show();
}
其中定义的列表是上下文菜单的标题列表(应该在某处生成)。
在listBoxTap事件中:
private void contextMenu_ListBoxTap(object sender, EventArgs e)
{
int index = contextMenu.ListBox.SelectedIndex;
switch (index)
{
// items index starts with zero
case 0:
// Call the click event for this one, it should be implemented already, when we've written it for native context menu
MiClickEvent(this, EventArgs.Empty);
contextMenu.Close();
break;
// implement other handlers here
default:
contextMenu.Close();
break;
}
这是唯一的解决方案,真的对我有所帮助。希望它能帮助别人。