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

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

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


当前回答

在检查正则表达式之前,我修改了Rays answer以处理突出显示的文本。我还将正则表达式调整为只允许小数点后两位(货币)。

private static readonly Regex _regex = new Regex(@"^[0-9]\d*(\.\d{0,2})?$");
private static bool IsTextAllowed(string text)
{
    return _regex.IsMatch(text);
}

private bool IsAllowed(TextBox tb, string text)
{
    bool isAllowed = true;
    if (tb != null)
    {
        string currentText = tb.Text;
        if (!string.IsNullOrEmpty(tb.SelectedText))
            currentText = currentText.Remove(tb.CaretIndex, tb.SelectedText.Length);
        isAllowed = IsTextAllowed(currentText.Insert(tb.CaretIndex, text));
    }
    return isAllowed;
}

private void Txt_PreviewCurrencyTextInput(object sender, TextCompositionEventArgs e)
{
    e.Handled = !IsAllowed(sender as TextBox, e.Text);            
}


private void TextBoxPasting(object sender, DataObjectPastingEventArgs e)
{
    if (e.DataObject.GetDataPresent(typeof(String)))
    {
        String text = (String)e.DataObject.GetData(typeof(String));
        if (!IsAllowed(sender as TextBox, text))
            e.CancelCommand();
    }
    else
        e.CancelCommand();
}

还有xaml

<TextBox Name="Txt_Textbox" PreviewTextInput="Txt_PreviewCurrencyTextInput"  DataObject.Pasting="TextBoxPasting" />

其他回答

这里有一个非常简单和容易的方法来做到这一点使用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();
    }
}

也可以简单地实现一个验证规则,并将其应用到TextBox:

  <TextBox>
    <TextBox.Text>
      <Binding Path="OnyDigitInput" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
        <Binding.ValidationRules>
          <conv:OnlyDigitsValidationRule />
        </Binding.ValidationRules>
      </Binding>
    </TextBox.Text>

实现如下规则(使用与其他答案中建议的相同的Regex):

public class OnlyDigitsValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        var validationResult = new ValidationResult(true, null);

        if(value != null)
        {
            if (!string.IsNullOrEmpty(value.ToString()))
            {
                var regex = new Regex("[^0-9.-]+"); //regex that matches disallowed text
                var parsingOk = !regex.IsMatch(value.ToString());
                if (!parsingOk)
                {
                    validationResult = new ValidationResult(false, "Illegal Characters, Please Enter Numeric Value");
                }
            }
        }

        return validationResult;
    }
}

我假设:

您希望允许数字输入的文本框的文本属性最初设置为一些有效的数字值(例如,2.7172)。 文本框是主窗口的子窗口 你的主窗口是Window1类 您的文本框名称是numericTB

基本思想:

Add: private string previousText; to your main window class (Window1) Add: previousText = numericTB.Text; to your main window constructor Create a handler for the numericTB.TextChanged event to be something like this: private void numericTB_TextChanged(object sender, TextChangedEventArgs e) { double num = 0; bool success = double.TryParse(((TextBox)sender).Text, out num); if (success & num >= 0) previousText = ((TextBox)sender).Text; else ((TextBox)sender).Text = previousText; }

这将继续设置previousText为numericTB。文本只要它是有效的,并设置numericTB。如果用户写了您不喜欢的内容,则将文本转换到其最后一个有效值。当然,这只是基本的想法,它只是“傻瓜抵抗”,而不是“傻瓜证明”。例如,它不能处理用户乱用空格的情况。所以这里有一个完整的解决方案,我认为是“白痴证明”,如果我错了,请告诉我:

Content of your Window1.xaml file: <Window x:Class="IdiotProofNumericTextBox.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <TextBox Height="30" Width="100" Name="numericTB" TextChanged="numericTB_TextChanged"/> </Grid> </Window> Content of your Window.xaml.cs file: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace IdiotProofNumericTextBox { public partial class Window1 : Window { private string previousText; public Window1() { InitializeComponent(); previousText = numericTB.Text; } private void numericTB_TextChanged(object sender, TextChangedEventArgs e) { if (string.IsNullOrEmpty(((TextBox)sender).Text)) previousText = ""; else { double num = 0; bool success = double.TryParse(((TextBox)sender).Text, out num); if (success & num >= 0) { ((TextBox)sender).Text.Trim(); previousText = ((TextBox)sender).Text; } else { ((TextBox)sender).Text = previousText; ((TextBox)sender).SelectionStart = ((TextBox)sender).Text.Length; } } } } }

就是这样。如果你有很多文本框,那么我建议创建一个CustomControl继承从TextBox,所以你可以包装previousText和numericTB_TextChanged在一个单独的文件。

扩展的WPF工具包有一个:NumericUpDown

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

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