概述

UWP Community Toolkit Extensions 中有一个为TextBox 提供的 SurfaceDial 扩展 - SurfaceDialTextbox,本篇我们结合代码详细讲解 SurfaceDialTextbox 的实现。

SurfaceDialTextbox 为 TextBox 提供了一种简单的 Surface Dial 的菜单和操作方式,支持设置 TextBox 操作在 Dial 中的圆形菜单,选择后旋转 Dial 可以方便的对 TextBox 中的数值进行调整,调整方式类似于 NumericUpdown,可以设置数值上限和下限,以及步长;旋转 Dial 可以选择有震动反馈,超过界限后也会有反馈提示,点按 Dial 可以选择 Focus 到下一个 Element。接下来看看官方示例的截图:

Source: https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI/Extensions/SurfaceDialTextbox

Doc: https://docs.microsoft.com/zh-cn/windows/uwpcommunitytoolkit/extensions/surfacedialtextboxhelper

Namespace: Microsoft.Toolkit.Uwp.UI.Extensions; Nuget: Microsoft.Toolkit.Uwp.UI;

开发过程

代码分析

SurfaceDialTextbox 的处理在类 SurfaceDialTextbox.cs 中,我们先来看看类的结构:

可以看到类中定义了如下的依赖属性:

  • ForceMenuItem - 标志是否强制在 Surface Dial 上下文菜单中加入 SurfaceDialTextbox 对应的菜单,如果应用中没有其他控制器,则需要设置为 True;如果有,则设置一致即可;
  • Icon - SurfaceDialTextbox 在 Surface Dial 上下文菜单中显示的 Icon,类型是 RadialControllerMenuKnownIcon,枚举类型;默认为 Ruler;
  • StepValue - 标志了旋转 Surface Dial 时,每旋转一次对应的数值变化步长;变化时触发 StepValueChanged 事件;
  • EnableHapticFeedback - 标志了是否允许在旋转 Surface Dial 时的震动反馈;
  • MinValue - 数值变化的最小值;默认为 -100;
  • MaxValue - 数值变化的最大值;默认为 100;
  • EnableTapToNextControl - 标志是否在点击 Surface Dial 时,将 Focus 移动到下一个 Item;适用于表单类场景,需要切换多个 TextBox;
  • EnableMinMaxValue - 标志是否为 SurfaceDialTextbox 设置数值最小值和最大值;

然后我们看几个全局静态变量:

  • _controller - RadialController 类型,是 Surface Dial controller 实例;
  • Controller - _controller 对应的 public 类型,支持在调用代码中获取 Surface Dial controller 实例,用于 SurfaceDialTextbox 之外的控件上;
  • _stepTextMenuItem - RadialControllerMenuItem 类型,在 Surface Dial 上下文菜单中显示的菜单项;
  • _textBox - SurfaceDialTextbox 对应的 textBox 控件;

接下来看几个 SurfaceDialTextbox 对应的主要处理方法:

1. Controller_RotationChanged(sender, args)

Surface Dial 旋转时触发的事件处理方法,根据当前显示的 Text,获取对应的 double 类型值;根据当前 Dial 旋转角度和 StepValue 来判断数值的变化,如果允许最大最小值区间限制,则判断是否越界后设置数值;如果 Text 不是数值,则设置默认值 0.0;

private static void Controller_RotationChanged(RadialController sender, RadialControllerRotationChangedEventArgs args)
{
    if (_textBox == null)
    {
        return;
    }

    string t = _textBox.Text;
    double nr;

    if (double.TryParse(t, out nr))
    {
        nr += args.RotationDeltaInDegrees * GetStepValue(_textBox);
        if (GetEnableMinMaxValue(_textBox))
        {
            if (nr < GetMinValue(_textBox))
            {
                nr = GetMinValue(_textBox);
            }

            if (nr > GetMaxValue(_textBox))
            {
                nr = GetMaxValue(_textBox);
            }
        }
    }
    else
    {
        // default to zero if content is not a number
        nr = 0.0d;
    }

    _textBox.Text = nr.ToString("0.00");
}

2.  StepValueChanged(d, e)

StepValue 属性改变时触发事件的处理逻,为 textBox 设置 GotFocus 和 LostFocus 事件绑定,我们来看看这两个事件的处理:

TextBox_GotFocus(sender, e) 处理逻辑:获取 Radial Controller,如果需要添加 MenuItem,则根据设置添加对应的 MenuItem;设置转动时的震动反馈,旋转的步长,旋转变化事件;如果允许点击 Focus 到下一个控件,则设置 Radial Controller 的 点击事件;

private static void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    _textBox = sender as TextBox;

    if (_textBox == null)
    {
        return;
    }

    if (!IsSupported)
    {
        return;
    }

    _controller = _controller ?? RadialController.CreateForCurrentView();

    if (GetForceMenuItem(_textBox))
    {
        _stepTextMenuItem = RadialControllerMenuItem.CreateFromKnownIcon("Step Text Box", GetIcon(_textBox));
        _controller.Menu.Items.Add(_stepTextMenuItem);
        _controller.Menu.SelectMenuItem(_stepTextMenuItem);
    }

    _controller.UseAutomaticHapticFeedback = GetEnableHapticFeedback(_textBox);
    _controller.RotationResolutionInDegrees = ;
    _controller.RotationChanged += Controller_RotationChanged;
    if (GetEnableTapToNextControl(_textBox))
    {
        _controller.ButtonClicked += Controller_ButtonClicked;
    }
}

TextBox_LostFocus(sender, e)  GotFocus 事件对应的相反处理,作用是在 Radial Controller menu 中去掉对应的 MenuItem;解除 RotationChanged 和 Controller_ButtonClicked 事件的绑定;

private static void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
    if (_textBox == null)
    {
        return;
    }

    if (GetForceMenuItem(_textBox))
    {
        _controller.Menu.Items.Remove(_stepTextMenuItem);
    }

    _controller.RotationChanged -= Controller_RotationChanged;
    if (GetEnableTapToNextControl(_textBox))
    {
        _controller.ButtonClicked -= Controller_ButtonClicked;
    }

    _textBox = null;
}

调用示例

我们设置一个 SurfaceDialTextbox,默认值为 0,每次变化为 1,区间是 0~100;来看第一张图中,点按 Dial 时会出现 SurfaceDialTextbox 的菜单,菜单图标是尺子;点按后可以通过旋转来改变 textbox 的值;如果初始时不点按 Dial,直接旋转也是一样改变 textbox 的值;在值超出 0~100 区间时,Dial 会有震动反馈;

<TextBox HorizontalAlignment="Left"
        VerticalAlignment="Top"
        Margin="0,0,0,10"
        Text="0"
        Width="250" Height="50" FontSize="20"
        extensions:SurfaceDialTextbox.StepValue="1"
        extensions:SurfaceDialTextbox.ForceMenuItem="True"
        extensions:SurfaceDialTextbox.EnableHapticFeedback="True"
        extensions:SurfaceDialTextbox.EnableMinMaxValue="True"
        extensions:SurfaceDialTextbox.MinValue="0"
        extensions:SurfaceDialTextbox.MaxValue="100"
        extensions:SurfaceDialTextbox.Icon="Ruler"
     extensions:SurfaceDialTextbox.EnableTapToNextControl="True"/>

 

总结

到这里我们就把 UWP Community Toolkit Extensions 中的 SurfaceDialTextbox 的源代码实现过程和简单的调用示例讲解完成了,希望能对大家更好的理解和使用这个扩展有所帮助。欢迎大家多多交流,谢谢!

最后,再跟大家安利一下 UWPCommunityToolkit 的官方微博:https://weibo.com/u/6506046490大家可以通过微博关注最新动态。

衷心感谢 UWPCommunityToolkit 的作者们杰出的工作,Thank you so much, UWPCommunityToolkit authors!!!

Extensions in UWP Community Toolkit - SurfaceDialTextbox的更多相关文章

  1. Extensions in UWP Community Toolkit - Overview

    概述 UWP Community Toolkit  中有一个 Extensions 的集合,它们可以帮助开发者实现很多基础功能,省去自己造轮子的过程,本篇我们先来看一下 Extensions 的功能都 ...

  2. Extensions in UWP Community Toolkit - FrameworkElement Extensions

    概述 UWP Community Toolkit Extensions 中有一个为FrameworkElement 提供的扩展 - FrameworkElement Extensions,本篇我们结合 ...

  3. Extensions in UWP Community Toolkit - Mouse Cursor

    概述 UWP Community Toolkit Extensions 中有一个为 Mouse 提供的扩展 - Mouse Cursor Extensions,本篇我们结合代码详细讲解 Mouse C ...

  4. Extensions in UWP Community Toolkit - ViewExtensions

    概述 UWP Community Toolkit Extensions 中有一个为 View 提供的扩展 - View Extensions,本篇我们结合代码详细讲解 View Extensions  ...

  5. Extensions in UWP Community Toolkit - Visual Extensions

    概述 UWP Community Toolkit Extensions 中有一个为可视元素提供的扩展 - VisualExtensions,本篇我们结合代码详细讲解 VisualExtensions ...

  6. Extensions in UWP Community Toolkit - WebViewExtensions

    概述 UWP Community Toolkit Extensions 中有一个为 WebView 提供的扩展 - WebViewExtensions,本篇我们结合代码详细讲解 WebView Ext ...

  7. Extensions in UWP Community Toolkit - ListViewExtensions

    概述 UWP Community Toolkit Extensions 中有一个为 ListView 提供的扩展 - ListViewExtensions,本篇我们结合代码详细讲解 ListView  ...

  8. New UWP Community Toolkit

    概述 UWP Community Toolkit 是一个 UWP App 自定义控件.应用服务和帮助方法的集合,能够很大程度的简化和指引开发者的开发工作,相信广大 UWPer 并不陌生. 下面是截取自 ...

  9. Animations in UWP Community Toolkit - Overview

    概述 UWP Community Toolkit  中有一个 Animations 的集合,它们可以帮助开发者实现很多的动画,本篇我们先来看一下 Animations 的功能都有哪些,再后面会针对每一 ...

随机推荐

  1. python学习03-数据类型

    一.基本数据类型--数字 布尔型 bool型只有两个值:True和False 之所以将bool值归类为数字,是因为我们也习惯用1表示True,0表示False. 以下是布尔值是False的各种情况: ...

  2. 笔记:Struts2 Action 非泛型集合元素类型转换

    局部类型转换文件 局部类型转换文件的文件名应为 ActionName-conversion.properties,其中 ActionName 是需要替换为 Action 的类名称,后面的 conver ...

  3. 兼容的Ajax

    /** * 创建XMLHttpRequest对象 * @param _method 请求方式: post||get * @param _url 远程服务器地址 * @param _async 是否异步 ...

  4. 漫谈Java IO之基础篇

    Java的网络编程如果不是专门搞服务器性能开发或者消息分发,几乎可能涉及不到.但是它却是面试找工作必问的一个知识点,涵盖的知识体系也非常广泛,从Java底层IO原理到操作系统内核组成,再到网络TCP. ...

  5. 分析 webpack 打包后的代码

    写在前面的:使用的 webpack 版本 3.0.0 一.开始 1. 准备 当前只创建一个文件 index.js,该文件作为入口文件,代码如下. console.log('hello, world') ...

  6. [HNOI2002]营业额统计_Treap

    [HNOI2002]营业额统计 题目大意:给你一串n数序列,对于每一个刚输入的数a,找到一个前面的数k,使得|a-k|最小. 注释:$n<=32767,ai<=10^6$. 想法:刚学Tr ...

  7. 安装texlive2017(latex的编译软件)

    准备工作是先卸载老版本的texlive,这个只要找到原来安装时的安装目录,然后直接把整个文件夹删掉即可.然后找到最近的Ctan的镜像,下载到对应版本的texlive,例如Mac系统,最好用的就是tex ...

  8. %f使用时的注意事项

    1不是所有定义都用int,使用浮点函数需要把int改成float才能正常工作 2保留一位小数时要打入%0.1f,保留两位小数时要打入%0.2f,而不是%0.01f

  9. Alpha冲刺No.10

    一.站立式会议 我们的阿尔法冲刺也基本宣告血崩,虽然很多功能已经实现,但是并没有串联在一起,好在这周不需要上课,我们也能好好睡一觉 实现手机的定位系统 细化界面设计 解决数据库和软件交互的一些问题 二 ...

  10. Bate敏捷冲刺每日报告--day3

    1 团队介绍 团队组成: PM:齐爽爽(258) 小组成员:马帅(248),何健(267),蔡凯峰(285)  Git链接:https://github.com/WHUSE2017/C-team 2 ...