Windows Phone 8.1文本框字符虚拟键验证

2023-12-14

我正在开发 Windows Phone 8.1 应用程序。 在文本框中,我想阻止用户仅输入任何非数字字母 [0-9]。

所以这是我的代码:

 private void NumKeyDown(object sender, KeyRoutedEventArgs e)
        {

           bool isNumber = (e.Key == Windows.System.VirtualKey.Number0 ||
                 e.Key == VirtualKey.Number1 ||
                 e.Key == VirtualKey.Number2 ||
                 e.Key == VirtualKey.Number3 ||
                 e.Key == VirtualKey.Number4 ||
                 e.Key == VirtualKey.Number5 ||
                 e.Key == VirtualKey.Number6 ||
                 e.Key == VirtualKey.Number7 ||
                 e.Key == VirtualKey.Number8 ||
                 e.Key == VirtualKey.Number9 ||
                 e.Key == VirtualKey.Back);

            CoreVirtualKeyStates shiftState = Window.Current.CoreWindow.GetKeyState(VirtualKey.Shift);


            bool shiftIsNotDown = true;
            if ((shiftState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down)
                shiftIsNotDown = false;

            e.Handled = !(isNumber && shiftIsNotDown);

        }

它有效,但有两个主要缺陷:

1-它也接受移位字符(即!@#$%^&*),而这是不需要的。

2-当我启动应用程序时,文本框填充了一个数字。我可以输入任何数字或字符(!@#$%^),也可以使用删除BACKSPACE。在此期间ShiftState is NONE。但是,一旦我使用删除文本框中的所有内容BACKSPACE the ShiftState更改为 [locked | Down],我无法在该文本框中输入任何内容。

请注意,我从来没有碰过 Shift 按钮!

我哪里错了??

UPDATE

我发现使用滑动功能将输入文本字母,而不会触发我正在应用的 keyDown 事件:(

任何帮助表示赞赏


好的,我将根据我在这里收到的回复以及过去几天所做的研究来尝试回答这个问题。答案将分为两部分 [旁注 - 解决方案]

如果您对我觉得有兴趣与读者分享的问题的细节不感兴趣,您可以跳到(解决方案部分)

附注:

我注意到以下问题

  1. 最重要的是window 8.1和xaml和winRT 文档非常差,而且几乎毫无用处。我希望有人 来自 Microsoft winRT 团队的人员正在阅读本文。除非他们正在做 这是故意迫使大多数开发人员转向 C++。

  2. 关于测试我的应用程序。我使用了 3 种[[不同]]输入法。如下图:

keyBoards

结果与 KeyDown 事件不同且不一致,如下所示:

让我假设我想输入字符(&)

  • 在模拟器键盘上:keyDown 事件 Arg e.Key = 数字 7。
  • 在 PC 触摸键盘上:KeyDown 事件将触发两次。在里面 第一次 e.Key 代码将被移位,第二次 keyDown 事件 e.Key 将为 Number7
  • 在物理键盘上,当然会触发两个 keyDown 事件。 你必须先按 Shift 然后按 Number7 才能得到 (&)。

我还注意到在物理键盘上,无论您按哪个档位(即向右或向左),KeyDown 事件e.Key将会呈现LeftShift !!

我不知道这对我的电脑键盘来说是否是特殊情况,但所有这些发现都表明 keyDown 并不真正值得信赖,并且这里缺乏文档

我注意到我无法控制的另一个发现:

  • 当您将焦点移至空文本框时,Shift 按钮将 进入锁定状态(以大写开头的句子 信)。因此任何 keyDown 事件都会首先触发 Shift 键,然后触发 您按下的字母。如果您不知道,这可能会让您感到困惑 关于它 。

我要感谢@Bryan Stump,带我访问微软链接微软论坛这向我展示了了解情况的重要信息:

“正如 Shiva 的代码所示,跟踪 KeyUp 和 KeyDown 将适用于 有限的情况,但不是全部。例如,它不适用于墨水或(我 认为)IME 输入。它还对键盘布局做出假设 不适用于所有键盘。除非你能限制自己的 满足非常具体的基本场景的要求是唯一的方法 成功地限制输入是在事后才这样做。” Rob Caplan [微软金融时报]

此链接向我保证,唯一可用的方法是接受该字符,然后在不适合您的验证的情况下将其删除,因此引用:“事后这样做”。

最后,我要感谢@Hans Passant 的简短评论,让我走上了正轨:

“改用 CoreWindow.CharacterReceived”。

之后我开始搜索,我发现的关于 CoreWindow.CharacterReceived 的唯一好例子是堆栈溢出

从那里我开始了我的解决方案如下。

解决方案:

介绍:

  • 第一:你不能拦截角色并阻止它到达 文本框。

  • 第二:你不能使用 keyDown 或 keyUp 事件来知道是什么 特点。你只能知道按下的键而不是 性格产生了。

  • 第三:给你角色奖励的事件被命名
    “CoreWindow.CharacterReceived”,但请注意,您会知道
    写入文本框后的字符。正是在这一点上你 可以选择接受或删除

  • 第四:由于字符是在文本框中接收的,所以
    处理它的正确方法是事件textChanged。

  • 第五:也是最重要的;那是CharacterReceived event 将要 在单词中的每个字母上循环射击,这需要特殊的操作和验证

因此,基于上述五个事实,伪代码将是:

依靠正则表达式来验证文本并接受它;否则,如果输入无效,则恢复之前的状态textBox.Text

string txtTemp = "";
    private void changedText(object sender, TextChangedEventArgs e)
    {

    Regex regex = new Regex(@"^\d{1,4}$");


string txtToTest = txtNumber.Text;


    if (regex.IsMatch(txtToTest)|| txtNumber.Text=="")
    {
//do nothing 
    }
    else
    {
        txtNumber.Text = txtTemp;
        txtNumber.Select(txtNumber.Text.Length, 0);
    }

//Save the current value to resume it if the next input was invalid
    txtTemp = txtNumber.Text;
}

上述解决方案适合我的情况,我想确保用户仅输入数字。然而,有些情况下,您想确保用户输入特定的字母,并且您需要根据按下的字母进行响应!在这种情况下,您将需要以下解决方案,该解决方案是不完整的,并且缺乏用户可能从剪贴板(粘贴)输入字母或使用键盘的 swype 功能输入字母的所有可能场景。

这里针对需要逐字母(逐键)控制输入的场景提供解决方案:

1-自从CoreWindow.CharacterReceived事件不是特定于文本框的(它是窗口/页面事件)。因此,只要您的文本框获得焦点,您就可以将其连接起来。并在文本框失去焦点时取消连接。

2- 听keyDow event。每当它被触发时,保存textBox.Text临时变量的值txtTemp.

3-设置一个布尔值,指示接收到的字符是否被接受(bool acceptChange = true)。并使用 CoreWindow.CharacterReceived 事件将此布尔值设置为 true 或 false(接受/不接受)

4- 在 textChange 事件中,如果 bool AcceptChange 为 true,则不执行任何操作。如果 bool AcceptChange 为 false,则将 textBox.Text 值重置为您在 keyDown 事件期间保存的临时值 ( txtBox.Text = txtTemp )

通过这个解决方案,我们可以确保只接受我们想要的字符,只留下一个小问题,如下所示:

假设您将验证规则设置为仅接受数字。和textBox.Text =“752”。 如果用户输入字母“v”,则 txtTemp 将为“752”,txtBox.Text 的新值将为“752v”,并且在 textChange 事件中,我们会将值重置为之前的值(即“752”)。这是通过 keydown 事件的帮助来完成的。

但是如果用户没有输入字母“v”,而是从其他地方复制它并使用粘贴功能,那么 txtBox.Text 的新值 =“752v”,但 txtTemp 将是“75”,因为 keYDown甚至没有触发捕获最新的txtBox值:(

在这里,textBox 事件“paste”的重要性就显现出来了。

所以我的伪代码中的第 5 步是:

5- 在txtBox.paste事件 请确保您通过以下方式取消此事件e.Handled=true;

现在我来看看代码:

//this is critical to wire up the "Window.Current.CoreWindow.CharacterReceived" event when 
//the textBox get focus and to unwire it when the textBox lose focus.
// notice that the whole page is listening not only the textBox

    private void txtBox_GotFocus(object sender, RoutedEventArgs e)
    {
        Window.Current.CoreWindow.CharacterReceived += inputEntered;
    }

    private void txtBox_LostFocus(object sender, RoutedEventArgs e)
    {
        Window.Current.CoreWindow.CharacterReceived -= inputEntered;
    }



// temporary variable for holding the latest textBox value before the textChange event is trigerred
    string txtTemp = "";

    private void txtBox_KeyDown(object sender, KeyRoutedEventArgs e)
    {
        //whenever a key is pressed, capture the latest textBox value
        txtTemp= txtBox.Text;

    }

// this boolean is to be used by the textChanged event to decide to accept changes or not
    bool acceptChange = true;

// here we recieve the character and decide to accept it or not.
    private void inputEntered(CoreWindow sender, CharacterReceivedEventArgs args)
    {
    // reset the bool to true in case it was set to false in the last call
        acceptChange = true;

        Debug.WriteLine("KeyPress " + Convert.ToChar(args.KeyCode)+ "keyCode = "+ args.KeyCode.ToString());
        args.Handled = true;

    //in my case I needed only numeric value and the backSpace button 
        if ((args.KeyCode > 47 && args.KeyCode < 58) || args.KeyCode == 8)
        {
            //do nothing (i.e. acceptChange is still true)
        }
        else
        {
    //set acceptChange to false bec. character is not numeric nor backSpace
            acceptChange = false;
        }
    }



    private void txtBox_TextChanged(object sender, TextChangedEventArgs e)
    {
    //the code here is my validation where I want only 3 digits number with no decimal
        if (txtBox.Text.Length < 4)
        {
            if (acceptChange)
            {
        // do nothing
            }
            else
            {
                txtBox.Text = txtTemp;

        //this is to move the cursor to the end of the text in the textBox
                txtBox.Select(txtBox.Text.Length, 0);
            }
        }
        else
        {
            txtBox.Text = txtTemp;

        //this is to move the cursor to the end of the text in the textBox
            txtBox.Select(txtBox.Text.Length, 0);
        }


    }





// this is for the special case where the user input text using Paste function
    private void txtBox_Paste(object sender, TextControlPasteEventArgs e)
    {
        e.Handled=true;
    }

:)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Windows Phone 8.1文本框字符虚拟键验证 的相关文章

随机推荐

  • 验证 Firebase 键是否为整数

    这是数据库架构 规则如下 notifications year read false write data exists month read false write data exists day read false write dat
  • 仅根据索引计算第 N 个多重集组合(具有重复)

    我怎样才能仅根据它的索引来计算第 N 个组合 应该有 n k 1 k n 1 种重复组合 with n 2 k 5 you get 0 0 0 0 0 0 1 0 0 0 0 1 2 0 0 0 1 1 3 0 0 1 1 1 4 0 1
  • 构建后事件执行 PowerShell

    是否可以使用构建后事件设置 NET 项目来执行 powershell 脚本 我正在使用这个脚本来生成一些文件 我还可以将它是调试版本还是发布版本传递给脚本 举一个这样的例子就太好了 这是一个例子 首先 您必须意识到必须配置 PowerShe
  • 检查卸载前是否保存了更改

    我有以下 JavaScript 编辑 包含更改已保存的分配 var changesSaved true document ready function applyChanges click function e e preventDefau
  • HttpClient 正在发送额外的 cookie

    运行 UWP 应用 所以我有一个 HttpClient 及其关联的处理程序 我正在向网站发出请求 传入指定的标头 并使用指定的 CookieContainer 该 CookieContainer 在请求开始时为空 当我发送请求时 Fiddl
  • 如何抑制Spyder编辑器中的某个警告?

    在我输入该行后 Spyder 中的编辑器总是立即向我发出有关未使用的导入 变量的警告 我想抑制这样的警告 我怎么做 我希望我在 Spyder 编辑器中打开的每个文件都发生这种情况 不喜欢本地修复 我尝试添加 disable pylintrc
  • 设置名称时抛出异常

    我在设置名称时遇到强制转换异常 Object customers customerRepository getCustomerName Id Customer row new Customer row setName String cust
  • 是否可以使用标准库在 Go 中嵌套模板?

    如何在 python 运行时中获取像 Jinja 那样的嵌套模板 TBC 我的意思是如何让一堆模板从基本模板继承 只需归档基本模板块 就像 Jinja django templates 所做的那样 是否可以只使用html template在
  • 如何从 qdateEdit 获取用户输入并从 postgres 的数据库中选择它

    我想知道如何在 QDateEdit 中获取用户输入并在 postgres 的表中选择它 这是我的代码 def date self try date self dateEdit date print date conn psycopg2 co
  • 如何将 std::sort 与结构向量和比较函数一起使用?

    谢谢你的C 中的解决方案 现在我想使用 std sort 和向量在 C 中实现这一点 typedef struct double x double y double alfa pkt vector lt pkt gt wektor 使用pu
  • 如何在R中找到超过10个变量的第二、第三和第n最大行?

    我有一个包含 20 个变量的数据集 我需要使用其中的 10 个变量来查找第一个 第二个 第三个 第 n 个最大值 变量是x1 to x10 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 1 2 0 3 4 5 6 7 8 5
  • 全局临时表 - SQL Server 与 Oracle

    我使用 Oracle 11g 全局临时表 因为我需要一个解决方案 可以将行添加到临时表中以进行联接 并且我只希望添加到临时表中以包含 Oracle 连接 会话的行 我在 Oracle 中使用全局临时表 因为我希望该表存在于会话之间 这样就不
  • 检查每个进程和子进程的内存

    我试图创建一个脚本来显示 mysqld 的每个进程和子进程的使用量 您可以在我的代码中看到我做了什么 bin bash file contains the output of pstree mysql a p awk print 1 sed
  • Astar 可以多次访问节点吗?

    我一直在阅读维基百科的 Astararticle 在他们的实现中 他们检查每个节点是否在closed设置 如果是这样 他们会跳过它 是不是有可能 如果启发式是可以接受的 但是NOT一致 我们可能需要重新访问一个节点两次 或更多次 才能改进它
  • 注册 Office.EventType.ItemChanged 时 Outlook WebAddin 引发内部服务器错误

    在我的 Outlook WebAddin 中 我尝试使用以下代码注册邮件 ItemChange 事件 Office context mailbox addHandlerAsync Office EventType ItemChanged m
  • cygwin pthread_mutex_timedlock 代理

    不幸的是 cygwin GCC 4 5 3 pthread 库实现不支持 POSIX 标准函数 int pthread mutex timedlock pthread mutex t mutex struct timespec abstim
  • Colorbox 和通过 ajax 返回的内容

    我正在使用 jquery colorbox 在窗口中弹出用户帐户 我还有一个按钮 可以通过 ajax 将更多用户加载到页面中 但由于某种原因 使用 ajax 加载的用户不会在彩盒窗口中弹出 如何让 colorbox 处理通过 ajax 返回
  • 使用 BOOST_FUSION_ADAPT_ADT 调整类时出错

    我有以下课程 ifndef WFRACTAL FRACTAL METADATA H define WFRACTAL FRACTAL METADATA H include
  • python - Django内置登录视图不重定向到下一个

    我正在使用 django auth 视图进行身份验证 但成功登录后 它应该尝试将用户重定向到下一个 GET 参数 但它仅重定向到 LOGIN REDIRECT URL 这是我的网址 url r login auth views login
  • Windows Phone 8.1文本框字符虚拟键验证

    我正在开发 Windows Phone 8 1 应用程序 在文本框中 我想阻止用户仅输入任何非数字字母 0 9 所以这是我的代码 private void NumKeyDown object sender KeyRoutedEventArg