如何计算这些事件之后 WPF 文本框的文本
本文关键字:文本 之后 事件 WPF 何计算 计算 | 更新日期: 2023-09-27 17:56:32
我想将此TextBox
限制为仅取正整数,最多包括Int32.MaxValue
:
<TextBox Name="CurrentPageNumber"
PreviewTextInput="CurrentPageNumber_PreviewTextInput"
DataObject.Pasting="CurrentPageNumber_Pasting" />
我有以下事件:
private void CurrentPageNumber_Pasting(object sender, DataObjectPastingEventArgs e)
{
if (!e.DataObject.GetDataPresent(typeof(String)))
e.CancelCommand();
String text = (String)e.DataObject.GetData(typeof(String));
if (!IsPositiveInteger(text))
e.CancelCommand();
}
private bool IsPositiveInteger(String text)
{
if (text.Length <= 0 || ((int)text[0] == 48 && text.Length != 1)) // Restricts empty strings and numbers with preceding 0's except for 0 itself.
return false;
for (int i = 0; i < text.Length; i++)
{
var c = (int)text[i];
if (c < 48 || c > 57) // Check that all characters are between 0 and 9.
return false;
}
int result;
return Int32.TryParse(text, out result);
}
这还不够好,因为有人可以在文本框中已经有等效的整数值 Int32.MaxValue
(2147483647
),然后在它的右侧再加 1。如何通过预测事件操作后Text
的结果来使用我的IsPositiveInteger
方法?
这与阻止更改文本不同,但这是告诉用户"你不能把该文本放在这里"的习惯方式。我建议这样做,因为这是框架支持的方式,所以它最简单,通常框架支持的内容是人们最习惯在用户界面中看到的。我们习惯的,我们称之为"直觉"。
当用户更改该文本框中的文本时,将调用ValidationRule
。如果它返回一个false
ValidationResult
,用户将获得一个红色的错误边框,绑定属性不会更新,并且工具提示会告诉他他做错了什么。
如果你真的想坚持你最初的想法,你会发现你需要做很多工作。我不认为投资回报率证明这种努力是合理的,但是当我年轻的时候,我曾经用Perl写过一个二进制加法器,所以我没有资格扔任何石头。
在 WPF 中执行此类操作的传统方法是在Binding
上使用ValidationRule
。您没有绑定,因为您没有视图模型。这是一个几乎无法理解的异端邪说,它让我感到寒冷,但我们会努力的。我们将向代码隐藏添加一个属性,以便具有要绑定的内容。
public int NonNegativeIntValue { get; set; }
如果希望能够通过在代码隐藏中设置该属性来更新文本框,则必须采用INotifyPropertyChanged
路线。更好的是,使用视图模型;每次在 WPF 中没有视图模型的情况下执行任何操作时,事实证明,使用视图模型会更好。框架就像一个交通警察;承认它的权威,它会更容易相处。
然后我们会写一个ValidationRule
:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Controls;
namespace ValidationRules
{
public class PositiveIntegerRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
int result;
if (value.GetType() == typeof(String) && Int32.TryParse((String)value, out result) && result > 0)
return new ValidationResult(true, null);
return new ValidationResult(false, "Value must be a positive integer");
}
}
}
最后,我们将修复您的TextBox
:
<TextBox
Name="CurrentPageNumber"
xmlns:vr="clr-namespace:ValidationRules"
ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"
>
<TextBox.Text>
<Binding
Path="NonNegativeIntValue"
RelativeSource="{RelativeSource AncestorType=Window}"
>
<Binding.ValidationRules>
<vr:PositiveIntegerRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
我在这里做一个假设:您的代码隐藏类继承自Window
.如果它是UserControl
,则必须将绑定中的RelativeSource AncestorType=Window
更改为RelativeSource AncestorType=UserControl
- 无论正确。
除了 Ed 的答案之外,另一种方法是这样的,这种方式将确保 UI 始终显示一个可用的、可见的值,但它不那么干净,所以我建议人们像另一个答案一样使用验证规则(它更像 WPF)。另外,我的IsPositiveInteger
方法有错误;最初我想要 0,但现在我意识到因为我正在分页数据,我希望 1 作为起始页。
XAML:
<TextBox Name="CurrentPageNumber" TextChanged="CurrentPageNumber_TextChanged"/>
C#:
private bool IsPositive32BitInteger(String text)
{
if (text.Length <= 0 || (int)text[0] == 48) // Restricts empty strings and numbers with preceding 0's or 0 itself.
return false;
for (int i = 0; i < text.Length; i++)
{
var c = (int)text[i];
if (c < 48 || c > 57) // Check that all characters are between 0 and 9.
return false;
}
int result;
return Int32.TryParse(text, out result);
}
private void CurrentPageNumber_TextChanged(object sender, TextChangedEventArgs e)
{
var textBox = (TextBox)sender;
if (textBox.Text.Length <= 0)
{
textBox.Text = "1";
return; // Set text to "1" as default and return. The event will fire again since we set the Text property.
}
if (textBox.Text.StartsWith("0"))
{
textBox.Text = textBox.Text.TrimStart(new char[] { '0' });
return; // Trim the text and return. The event will fire again since we set the Text property.
}
if (!IsPositive32BitInteger(textBox.Text)) {
textBox.Text = "1";
return; // Set text to "1" as default and return. The event will fire again since we set the Text property.
}
// At this point the value is forced into the state you want and you can do other stuff.
}