我希望接受数字和小数点,但没有符号。

我已经看过使用Windows窗体中的NumericUpDown控件的示例,以及来自微软的这个NumericUpDown自定义控件的示例。但到目前为止,似乎NumericUpDown (WPF是否支持)不会提供我想要的功能。我的应用程序是这样设计的,任何头脑正常的人都不会想弄乱箭头。在我的应用程序中,它们没有任何实际意义。

所以我正在寻找一个简单的方法,使一个标准的WPF文本框只接受我想要的字符。这可能吗?实用吗?


当前回答

最好和最优雅的解决方案,只允许整数在文本框(甚至在某些范围)是:

XAML:

<TextBox PreviewTextInput="ValidationTextBox" TextChanged="TextBox_TextChanged"/>

C#:

private void ValidationTextBox(object sender, TextCompositionEventArgs e)
{
    int max = 100;

    //do not allow futher incorrect typing
    e.Handled = !(int.TryParse(((TextBox)sender).Text + e.Text, out int i) && i >= 1 && i <= max);
}

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    int max = 100;

    if (!int.TryParse(((TextBox)sender).Text, out int j) || j < 1 || j > max)
    {
        //delete incoret input
        ((TextBox)sender).Text = "";
    }
    else
    {
        //delete leading zeros
        ((TextBox)sender).Text = j.ToString();
    }
}

你可以调整最小和最大可接受的数字与max (min)通过开关((TextBox)sender). name。

此解决方案不允许输入的前导零或复制粘贴。在每个场景中,文本框中都有一个正确的数字。

其他回答

这里有一个非常简单和容易的方法来做到这一点使用MVVM。

在视图模型中绑定一个整数属性的文本框,这将像宝石一样工作…它甚至会在文本框中输入非整数时显示验证。

XAML代码:

<TextBox x:Name="contactNoTxtBox"  Text="{Binding contactNo}" />

查看模型代码:

private long _contactNo;
public long contactNo
{
    get { return _contactNo; }
    set
    {
        if (value == _contactNo)
            return;
        _contactNo = value;
        OnPropertyChanged();
    }
}

我们可以对文本框更改事件进行验证。下面的实现可以防止除数字和一个小数点以外的按键输入。

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;     
} 

受雷的启发,我有一个简单的解决方案。这应该足以识别任何形式的数字。

如果您只想要正数、整数值或精确到小数点后最大位数的值,则可以轻松修改此解决方案。


正如Ray的回答所建议的,你需要首先添加一个PreviewTextInput事件:

<TextBox PreviewTextInput="TextBox_OnPreviewTextInput"/>

然后把下面的代码放在后面:

private void TextBox_OnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
    var textBox = sender as TextBox;
    // Use SelectionStart property to find the caret position.
    // Insert the previewed text into the existing text in the textbox.
    var fullText = textBox.Text.Insert(textBox.SelectionStart, e.Text);

    double val;
    // If parsing is successful, set Handled to false
    e.Handled = !double.TryParse(fullText, out val);
}

对于无效的空格,我们可以添加NumberStyles:

using System.Globalization;

private void TextBox_OnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
    var textBox = sender as TextBox;
    // Use SelectionStart property to find the caret position.
    // Insert the previewed text into the existing text in the textbox.
    var fullText = textBox.Text.Insert(textBox.SelectionStart, e.Text);

    double val;
    // If parsing is successful, set Handled to false
    e.Handled = !double.TryParse(fullText, 
                                 NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, 
                                 CultureInfo.InvariantCulture,
                                 out val);
}

这个怎么样?很适合我。希望我没有漏掉任何边缘情况……

MyTextBox.PreviewTextInput += (sender, args) =>
{
    if (!int.TryParse(args.Text, out _))
    {
        args.Handled = true;
    }
};

DataObject.AddPastingHandler(MyTextBox, (sender, args) =>
{
    var isUnicodeText = args.SourceDataObject.GetDataPresent(DataFormats.UnicodeText, true);
    if (!isUnicodeText)
    {
        args.CancelCommand();
    }

    var data = args.SourceDataObject.GetData(DataFormats.UnicodeText) as string;
    if (!int.TryParse(data, out _))
    {
        args.CancelCommand();
    }
});

在Windows窗体中,这很容易;你可以添加一个事件按键和一切工作轻松。然而,在WPF中该事件不存在。但是有一个更简单的方法。

WPF文本框有TextChanged事件,这是一般的一切。它包括粘贴,输入和任何你能想到的东西。

所以你可以这样做:

XAML:

<TextBox name="txtBox1" ... TextChanged="TextBox_TextChanged"/>

背后的代码:

private void TextBox_TextChanged(object sender, TextChangedEventArgs e) {
    string s = Regex.Replace(((TextBox)sender).Text, @"[^\d.]", "");
    ((TextBox)sender).Text = s;
}

这也是可以接受的。,如果你不想要它,只需将它从正则表达式语句中删除为@[^\d]。

注意:此事件可以用于许多TextBox元素,因为它使用发送方对象的文本。您只需编写一次事件,并且可以将其用于多个TextBox元素。