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

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

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


当前回答

e.Handled = (int)e.Key >= 43 || (int)e.Key <= 34;

在预览文本框的按键事件。

其他回答

这是我的版本。它基于一个基本的ValidatingTextBox类,如果它不是“有效”的,它只是撤销已经做过的事情。它支持粘贴,剪切,删除,退格,+,-等。

对于32位整型,有一个Int32TextBox类用于与整型进行比较。我还添加了浮点验证类。

public class ValidatingTextBox : TextBox
{
    private bool _inEvents;
    private string _textBefore;
    private int _selectionStart;
    private int _selectionLength;

    public event EventHandler<ValidateTextEventArgs> ValidateText;

    protected override void OnPreviewKeyDown(KeyEventArgs e)
    {
        if (_inEvents)
            return;

        _selectionStart = SelectionStart;
        _selectionLength = SelectionLength;
        _textBefore = Text;
    }

    protected override void OnTextChanged(TextChangedEventArgs e)
    {
        if (_inEvents)
            return;

        _inEvents = true;
        var ev = new ValidateTextEventArgs(Text);
        OnValidateText(this, ev);
        if (ev.Cancel)
        {
            Text = _textBefore;
            SelectionStart = _selectionStart;
            SelectionLength = _selectionLength;
        }
        _inEvents = false;
    }

    protected virtual void OnValidateText(object sender, ValidateTextEventArgs e) => ValidateText?.Invoke(this, e);
}

public class ValidateTextEventArgs : CancelEventArgs
{
    public ValidateTextEventArgs(string text) => Text = text;

    public string Text { get; }
}

public class Int32TextBox : ValidatingTextBox
{
    protected override void OnValidateText(object sender, ValidateTextEventArgs e) => e.Cancel = !int.TryParse(e.Text, out var value);
}

public class Int64TextBox : ValidatingTextBox
{
    protected override void OnValidateText(object sender, ValidateTextEventArgs e) => e.Cancel = !long.TryParse(e.Text, out var value);
}

public class DoubleTextBox : ValidatingTextBox
{
    protected override void OnValidateText(object sender, ValidateTextEventArgs e) => e.Cancel = !double.TryParse(e.Text, out var value);
}

public class SingleTextBox : ValidatingTextBox
{
    protected override void OnValidateText(object sender, ValidateTextEventArgs e) => e.Cancel = !float.TryParse(e.Text, out var value);
}

public class DecimalTextBox : ValidatingTextBox
{
    protected override void OnValidateText(object sender, ValidateTextEventArgs e) => e.Cancel = !decimal.TryParse(e.Text, out var value);
}

注意1:在使用WPF绑定时,必须确保使用符合绑定属性类型的类,否则可能会导致奇怪的结果。

注意2:在WPF绑定中使用浮点类时,请确保绑定使用当前区域性来匹配我使用的TryParse方法。

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

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

添加一个验证规则,以便在文本更改时检查数据是否是数字,如果是,则允许继续处理,如果不是,则提示用户该字段中只接受数字数据。

请参阅Windows演示基础中的验证

我在一个简单的项目中使用的是未绑定的盒子,所以我不能使用标准的绑定方法。因此,我创建了一个简单的黑客,其他人可能会发现非常方便,只需扩展现有的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" >

这是我用来获得一个接受数字和小数点的WPF文本框:

class numericTextBox : TextBox
{
    protected override void OnKeyDown(KeyEventArgs e)
    {
        bool b = false;
        switch (e.Key)
        {
            case Key.Back: b = true; break;
            case Key.D0: b = true; break;
            case Key.D1: b = true; break;
            case Key.D2: b = true; break;
            case Key.D3: b = true; break;
            case Key.D4: b = true; break;
            case Key.D5: b = true; break;
            case Key.D6: b = true; break;
            case Key.D7: b = true; break;
            case Key.D8: b = true; break;
            case Key.D9: b = true; break;
            case Key.OemPeriod: b = true; break;
        }
        if (b == false)
        {
            e.Handled = true;
        }
        base.OnKeyDown(e);
    }
}

将代码放在一个新的类文件中,添加

using System.Windows.Controls;
using System.Windows.Input;

并构建解决方案。numericTextBox控件将出现在工具箱的顶部。