0

在 Windows Phone 中有一个称为ContextMenu的功能,它允许为控件创建弹出菜单。

但是,如果菜单项列表很大,则其中一些不适合屏幕。下面的简单示例将说明这一点:

在xml中:

我们将使用 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>

成功?不,因为您可以滚动此列表,但不能向下选择项目。

我的问题是如何解决它?

使用多点触控?(我对此了解不多)

也许,我需要向 Scrollviewer 添加一些属性?

还有其他想法吗?

[更新]此外,如果添加了滚动查看器,则发现项目的点击/单击处理程序会更改行为。通常,当您点击该项目时,上下文菜单会关闭并执行处理程序方法。使用scrollviewer,上下文菜单不会关闭,需要再点击一次才能手动关闭。为什么会这样?

4

1 回答 1

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。简而言之,它是 Grid/StackPanel 上的一个简单的 TextBox。

将本机 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;
            }

这是唯一的解决方案,它真的帮助了我。希望它会帮助别人。

于 2013-02-20T06:01:54.050 回答