滚动文本菜单项(Scrolling ContextMenu items)

2019-08-07 00:49发布

Windows Phone中有一个名为文本菜单功能,它允许创建控件弹出菜单。

然而,如果菜单项列表中是相当大的,他们中的一些不适合在屏幕上。 下面简单的例子将展示这一点:

在XAML:

我们将使用工具包,因此增加

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中,上下文菜单没有关闭,需要一个更水龙头手动关闭它。 为什么是这种情况发生?

Answer 1:

如果原始文本菜单不允许这一点,那么,解决问题的最好办法,是写自己的实现。

新的上下文菜单应与几个项目可供选择的弹出显示,并且项目必须滚动。 所以:

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是一个用户控件,它应该看起来像本地的ContextMenuItem。 总之,一切都结束了网/ StackPanel的简单文本框。

原生文本菜单添加到XAML文件

<toolkit:ContextMenuService.ContextMenu>
        <toolkit:ContextMenu>
               <toolkit:MenuItem Header="..." ... Click="miClickEvent"/>
                <!-- ... --!>
        </toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>

相反,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;
            }

这是唯一的解决方案,真正帮助了我。 希望对大家有所帮助别人。



文章来源: Scrolling ContextMenu items