好的,我将根据我在这里收到的回复以及过去几天所做的研究来尝试回答这个问题。答案将分为两部分 [旁注 - 解决方案]
如果您对我觉得有兴趣与读者分享的问题的细节不感兴趣,您可以跳到(解决方案部分)
附注:
我注意到以下问题
最重要的是window 8.1和xaml和winRT
文档非常差,而且几乎毫无用处。我希望有人
来自 Microsoft winRT 团队的人员正在阅读本文。除非他们正在做
这是故意迫使大多数开发人员转向 C++。
关于测试我的应用程序。我使用了 3 种[[不同]]输入法。如下图:
结果与 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;
}
:)