• 【WP 8.1开发】上下文菜单


    在桌面系统中,别说是开发者,相信有资格考得过计算机一级的人都知道什么叫一下文菜单,或者叫右键菜单。

    为了让操作更方便,在手机应用程序中,也应当有这样的菜单。上下文菜单之所以有”上下文“之说,是因为通常它是与用户正在操作的对象有关联,比如,在文本输入框中选定一段文字,然后通过上下文菜单来设置选定文本的格式,菜单所操作的对象就是这些被选中的文本。

    在新的RT API中,有一个MenuFlyout类(从FlyoutBase派生,专用于一些弹出的浮动控件,菜单也是一种弹出控件),可以用它来创建上下文菜单。

    菜单中的每一项用MenuFlyoutItem类来表示,这是最常见的菜单,用得较多;还有一种ToggleMenuFlyoutItem菜单项,这种菜单项可以在多次点击之间切换状态,类似于我们在桌面程序中用到的可以Checked的菜单项,当状态是被选定时,前面会显示一个勾,当未选中时,前面没有勾。

    向应用程序UI添加上下菜单有两种方式。

    先说第一种,大家看看Button类,有没有发现它有个Flyout属性? 类型是FlyoutBase,这表明,只要从FlyoutBase类派生的控件都能用,正好,MenuFlyout类就是FlyoutBase的子类。因此,添加上下文菜单一种非常easy的方法就是直接赋给Button.Flyout属性。

    看例子:

            <Button Content="请点击" >
                <Button.Flyout>
                    <MenuFlyout>
                        <MenuFlyoutItem Text="选项一" Click="OnItemClick"/>
                        <MenuFlyoutItem Text="选项二" Click="OnItemClick"/>
                        <MenuFlyoutItem Text="选项三" Click="OnItemClick"/>
                    </MenuFlyout>
                </Button.Flyout>
            </Button>

    菜单中包含三个项,Text属性表示菜单中显示的文本,并可以通过处理菜单项的Click事件来响应用户操作。
    下面我们来写一些处理代码:

            private async void OnItemClick ( object sender, RoutedEventArgs e )
            {
                MenuFlyoutItem item = sender as MenuFlyoutItem;
                if (item != null)
                {
                    string msg = string.Format("你选择了“{0}”。", item.Text);
                    Windows.UI.Popups.MessageDialog dlg = new Windows.UI.Popups.MessageDialog(msg, "提示");
                    await dlg.ShowAsync();
                }
            }

    我不搞那么复杂了,就用一个方法同时处理三个MenuFlyoutItem的Click事件,通过sender就判断出哪个项被单击,然后用一个弹出对话框显示被单击的菜单项的文本。
    运行一下,然后点击那个可爱的按钮,会看到以下效果。

            

    运行后会发现,设置了Button.Flyout的弹出控件,只要一点击按钮,它就会自动显示,不需要我们做任何工作。

    另一种添加上下菜单的方法是通过附加属性的方法。

    FlyoutBase类定义了以下附加属性:

    public static Windows.UI.Xaml.DependencyProperty AttachedFlyoutProperty { get; }
    
    public static void SetAttachedFlyout(Windows.UI.Xaml.FrameworkElement element, Windows.UI.Xaml.Controls.Primitives.FlyoutBase value)
    
    public static Windows.UI.Xaml.Controls.Primitives.FlyoutBase GetAttachedFlyout(Windows.UI.Xaml.FrameworkElement element)

    通过这种附加属性,可以将上下文菜单附加到所有FrameworkElement对象上。

    注意,在这种情况下,MenuFlyout是不会自动弹出的,需要我们自己去处理。一般来说,当我们长按某个UI对象时打开菜单。比较好的做法是处理Holding事件,在手机上,长按就相当于我们在电脑上的鼠标右击。为什么不用RightTapped事件呢,因为RightTapped事件是需要完成整个长按操作后才会发生,而Holding在长按的操作过程中就能发生,如果用户一直按在UI对象上而不松开手,RightTapped事件延迟发生,用户看不到菜单出来,他会误以为程序有问题;反之,Holding事件在识别出用户长按操作后就会发生,用户在松开手指前就看到菜单出来,就不会误认为程序没反应了。

    看例子:

            <Ellipse Width="200" Height="200" Holding="OnElpHolding">
                <Ellipse.Fill>
                    <SolidColorBrush Color="Green" x:Name="elBrush"/>
                </Ellipse.Fill>
                <FlyoutBase.AttachedFlyout>
                    <MenuFlyout Placement="Top">
                        <MenuFlyoutItem Text="蓝色" Click="OnMenuClick" Tag="blue"/>
                        <MenuFlyoutItem Text="红色" Click="OnMenuClick" Tag="red"/>
                        <MenuFlyoutItem Text="绿色" Click="OnMenuClick" Tag="green"/>
                        <MenuFlyoutItem Text="紫色" Click="OnMenuClick" Tag="purple"/>
                    </MenuFlyout>
                </FlyoutBase.AttachedFlyout>
            </Ellipse>

    Placement属性是指定菜单弹出的方向,此处设置为向上。注意在WP中,菜单都是占用所有的水平空间的,也就是说当屏幕是纵向时,只有上、下两个方向是有意义的,左、右是会被忽略,因为左右的空间都被占满了,无所谓左右了。同理,当屏幕方向为横向时,只有左、右可用,因为上下都被菜单占满了。如果大家觉得不好理解也无所谓,这个位置也不是绝对的,系统会根据可用的空间自动调整,一般来说也不用刻意去指向菜单弹出的方向,我这里只是为了演示而设置的。

    首先,处理Ellipse的Holding事件,打开菜单。

            private void OnElpHolding ( object sender, HoldingRoutedEventArgs e )
            {
                Ellipse ellp = sender as Ellipse;
                if (ellp != null)
                {
                    // 显示上下文菜单
                    FlyoutBase.ShowAttachedFlyout(ellp);
                }
            }

    通过FlyoutBase类的静态方法ShowAttachedFlyout来打开菜单,参数就是附加了FlyoutBase.AttachedFlyout的UI元素,本例中是Ellipse对象。
    接下来,处理MenuFlyoutItem的Click事件,改变Ellipse的颜色。

            private void OnMenuClick ( object sender, RoutedEventArgs e )
            {
                MenuFlyoutItem item = sender as MenuFlyoutItem;
                if (item != null)
                {
                    string tag = item.Tag.ToString();
                    // 改变圆的颜色
                    switch (tag)
                    {
                        case "blue":
                            elBrush.Color = Colors.Blue;
                            break;
                        case "red":
                            elBrush.Color = Colors.Red;
                            break;
                        case "green":
                            elBrush.Color = Colors.Green;
                            break;
                        case "purple":
                            elBrush.Color = Colors.Purple;
                            break;
                        default:
                            elBrush.Color = Colors.Green;
                            break;
                    }
                }
            }

    运行示例,在圆上长按,就可以打开上下文菜单来改变圆的颜色了。

    示例源代码下载:http://files.cnblogs.com/tcjiaan/MenuFlyoutExamples.zip

    好了,今天的牛皮就吹到这里了,收笔。

    =============================================================

    必须严重地说一个事。希望转载博文者能注明原出处。博客是一个自由分享平台,但应该尊重原创,近来发现有些转载直接把原作者和原链接都去掉了,这是不厚道的。虽然我的博文写得比较烂,那也要尊重原创。  ——老周

  • 相关阅读:
    总结一下最近的工作状和提高效率的方式
    使用hash 算法把数据均匀的放在不同的数据库里面
    微服务-网关-全局过滤器鉴权(未使用spring security)
    Jwt 工具类
    Java泛型(二)<T> 和<?> 的区别
    final 和 static 的区别
    一面bytedance
    catalina.out 显示 端口占用
    No plugin found for prefix 'install' in the current project and in the plugin groups
    Mysql-sql查询技巧分析
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/4073173.html
Copyright © 2020-2023  润新知