我希望接受数字和小数点,但没有符号。
我已经看过使用Windows窗体中的NumericUpDown控件的示例,以及来自微软的这个NumericUpDown自定义控件的示例。但到目前为止,似乎NumericUpDown (WPF是否支持)不会提供我想要的功能。我的应用程序是这样设计的,任何头脑正常的人都不会想弄乱箭头。在我的应用程序中,它们没有任何实际意义。
所以我正在寻找一个简单的方法,使一个标准的WPF文本框只接受我想要的字符。这可能吗?实用吗?
我希望接受数字和小数点,但没有符号。
我已经看过使用Windows窗体中的NumericUpDown控件的示例,以及来自微软的这个NumericUpDown自定义控件的示例。但到目前为止,似乎NumericUpDown (WPF是否支持)不会提供我想要的功能。我的应用程序是这样设计的,任何头脑正常的人都不会想弄乱箭头。在我的应用程序中,它们没有任何实际意义。
所以我正在寻找一个简单的方法,使一个标准的WPF文本框只接受我想要的字符。这可能吗?实用吗?
当前回答
我允许数字键盘号码和退格:
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
int key = (int)e.Key;
e.Handled = !(key >= 34 && key <= 43 ||
key >= 74 && key <= 83 ||
key == 2);
}
其他回答
对于希望文本字段只接受无符号数字(如套接字端口等)的开发人员:
WPF
<TextBox PreviewTextInput="Port_PreviewTextInput" MaxLines="1"/>
C#
private void Port_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
e.Handled = !int.TryParse(e.Text, out int x);
}
下面的代码创建了一个控件,你将能够像正常的文本框一样使用,但它只会把一个正的双精度作为输入:
在XAML中,你可以这样使用这个控件:
<local:UnsignedDoubleBox/>
在c#代码中,在当前命名空间中添加以下内容:
public class UnsignedDoubleBox : TextBox
{
public UnsignedDoubleBox()
{
this.PreviewTextInput += defaultPreviewTextInput;
DataObject.AddPastingHandler(this, defaultTextBoxPasting);
}
private bool IsTextAllowed(TextBox textBox, String text)
{
//source: https://stackoverflow.com/questions/23397195/in-wpf-does-previewtextinput-always-give-a-single-character-only#comment89374810_23406386
String newText = textBox.Text.Insert(textBox.CaretIndex, text);
double res;
return double.TryParse(newText, out res) && res >= 0;
}
//source: https://stackoverflow.com/a/1268648/13093413
private void defaultTextBoxPasting(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(String)))
{
String text = (String)e.DataObject.GetData(typeof(String));
if (!IsTextAllowed((TextBox)sender, text))
{
e.CancelCommand();
}
}
else
{
e.CancelCommand();
}
}
private void defaultPreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (IsTextAllowed((TextBox)sender, e.Text))
{
e.Handled = false;
}
else
{
e.Handled = true;
}
}
}
我在一个简单的项目中使用的是未绑定的盒子,所以我不能使用标准的绑定方法。因此,我创建了一个简单的黑客,其他人可能会发现非常方便,只需扩展现有的TextBox控件:
namespace MyApplication.InterfaceSupport
{
public class NumericTextBox : TextBox
{
public NumericTextBox() : base()
{
TextChanged += OnTextChanged;
}
public void OnTextChanged(object sender, TextChangedEventArgs changed)
{
if (!String.IsNullOrWhiteSpace(Text))
{
try
{
int value = Convert.ToInt32(Text);
}
catch (Exception e)
{
MessageBox.Show(String.Format("{0} only accepts numeric input.", Name));
Text = "";
}
}
}
public int? Value
{
set
{
if (value != null)
{
this.Text = value.ToString();
}
else
Text = "";
}
get
{
try
{
return Convert.ToInt32(this.Text);
}
catch (Exception ef)
{
// Not numeric.
}
return null;
}
}
}
}
显然,对于浮动类型,您希望将其解析为浮动类型等等。同样的原则也适用。
然后在XAML文件中,你需要包含相关的命名空间:
<UserControl x:Class="MyApplication.UserControls.UnParameterisedControl"
[ Snip ]
xmlns:interfaceSupport="clr-namespace:MyApplication.InterfaceSupport"
>
之后,你可以把它作为一个常规的控制:
<interfaceSupport:NumericTextBox Height="23" HorizontalAlignment="Left" Margin="168,51,0,0" x:Name="NumericBox" VerticalAlignment="Top" Width="120" >
在使用这里的一些解决方案一段时间后,我开发了自己的解决方案,该解决方案适用于我的MVVM设置。注意,在允许用户输入错误字符的意义上,它不像其他一些那样动态,但它阻止用户按下按钮,从而阻止他们做任何事情。这很好地配合了我的主题,即当操作无法执行时将按钮变灰。
我有一个文本框,用户必须输入一些文档页面要打印:
<TextBox Text="{Binding NumberPagesToPrint, UpdateSourceTrigger=PropertyChanged}"/>
...使用这个绑定属性:
private string _numberPagesToPrint;
public string NumberPagesToPrint
{
get { return _numberPagesToPrint; }
set
{
if (_numberPagesToPrint == value)
{
return;
}
_numberPagesToPrint = value;
OnPropertyChanged("NumberPagesToPrint");
}
}
我还有一个按钮:
<Button Template="{DynamicResource CustomButton_Flat}" Content="Set"
Command="{Binding SetNumberPagesCommand}"/>
...使用此命令绑定:
private RelayCommand _setNumberPagesCommand;
public ICommand SetNumberPagesCommand
{
get
{
if (_setNumberPagesCommand == null)
{
int num;
_setNumberPagesCommand = new RelayCommand(param => SetNumberOfPages(),
() => Int32.TryParse(NumberPagesToPrint, out num));
}
return _setNumberPagesCommand;
}
}
然后是SetNumberOfPages()方法,但对于本主题不重要。它在我的案例中工作得很好,因为我不需要向视图的代码隐藏文件中添加任何代码,并且它允许我使用Command属性控制行为。
我们可以对文本框更改事件进行验证。下面的实现可以防止除数字和一个小数点以外的按键输入。
private void textBoxNumeric_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox textBox = sender as TextBox;
Int32 selectionStart = textBox.SelectionStart;
Int32 selectionLength = textBox.SelectionLength;
String newText = String.Empty;
int count = 0;
foreach (Char c in textBox.Text.ToCharArray())
{
if (Char.IsDigit(c) || Char.IsControl(c) || (c == '.' && count == 0))
{
newText += c;
if (c == '.')
count += 1;
}
}
textBox.Text = newText;
textBox.SelectionStart = selectionStart <= textBox.Text.Length ? selectionStart : textBox.Text.Length;
}