How do I get a TextBox to only accept numeric input in WPF?

后端 未结 30 2290
悲哀的现实
悲哀的现实 2020-11-22 03:40

I\'m looking to accept digits and the decimal point, but no sign.

I\'ve looked at samples using the NumericUpDown control for Windows Forms, and this sample of a Num

相关标签:
30条回答
  • 2020-11-22 04:09

    This is the only code needed:

    void MyTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
    {
        e.Handled = new Regex("[^0-9]+").IsMatch(e.Text);
    }
    

    This only allows numbers to be inputted into the text box.

    To allow a decimal point or minus sign, you can change the regular expression to [^0-9.-]+.

    0 讨论(0)
  • 2020-11-22 04:09

    Now I know this question has an accepted answer, but personally, I find it a bit confusing and I believe it should be easier than that. So I'll try to demonstrate how I got it to work as best as I can:

    In Windows Forms, there's an event called KeyPress which is perfectly good for this kind of task. But that doesn't exist in WPF, so instead, we'll be using the PreviewTextInput event. Also, for the validation, I believe one can use a foreach to loop through the textbox.Text and check if it matches ;) the condition, but honestly, this is what regular expressions are for.

    One more thing before we dive into the holy code. For the event to be fired, one can do two things:

    1. Use XAML to tell the program which function to call: <PreviewTextInput="textBox_PreviewTextInput/>
    2. Do it in the Loaded event of the form (which the textBox is in): textBox.PreviewTextInput += onlyNumeric;

    I think the second method is better because in situations like this, you'll mostly be required to apply the same condition (regex) to more than one TextBox and you don't want to repeat yourself!.

    Finally, here's how you'd do it:

    private void onlyNumeric(object sender, TextCompositionEventArgs e)
    {
        string onlyNumeric = @"^([0-9]+(.[0-9]+)?)$";
        Regex regex = new Regex(onlyNumeric);
        e.Handled = !regex.IsMatch(e.Text);
    }
    
    0 讨论(0)
  • 2020-11-22 04:09

    Use:

    Private Sub DetailTextBox_PreviewTextInput( _
      ByVal sender As Object, _
      ByVal e As System.Windows.Input.TextCompositionEventArgs) _
      Handles DetailTextBox.PreviewTextInput
    
        If _IsANumber Then
            If Not Char.IsNumber(e.Text) Then
                e.Handled = True
            End If
        End If
    End Sub
    
    0 讨论(0)
  • 2020-11-22 04:09

    I was working with an unbound box for a simple project I was working on, so I couldn't use the standard binding approach. Consequently I created a simple hack that others might find quite handy by simply extending the existing TextBox control:

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

    Obviously, for a floating type, you would want to parse it as a float and so on. The same principles apply.

    Then in the XAML file you need to include the relevant namespace:

    <UserControl x:Class="MyApplication.UserControls.UnParameterisedControl"
                 [ Snip ]
                 xmlns:interfaceSupport="clr-namespace:MyApplication.InterfaceSupport"
                 >
    

    After that you can use it as a regular control:

    <interfaceSupport:NumericTextBox Height="23" HorizontalAlignment="Left" Margin="168,51,0,0" x:Name="NumericBox" VerticalAlignment="Top" Width="120" >
    
    0 讨论(0)
  • 2020-11-22 04:09

    The following code creates a control which you will be able to use like a normal TextBox however it will only take a positive double as an input:

    In the XAML you'll be able to use this control like so:

    <local:UnsignedDoubleBox/>
    

    In the C# code add the following inside the current namespace:

    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;
                }
            }
    
        }
    
    0 讨论(0)
  • 2020-11-22 04:10

    Add a preview text input event. Like so: <TextBox PreviewTextInput="PreviewTextInput" />.

    Then inside that set the e.Handled if the text isn't allowed. e.Handled = !IsTextAllowed(e.Text);

    I use a simple regex in IsTextAllowed method to see if I should allow what they've typed. In my case I only want to allow numbers, dots and dashes.

    private static readonly Regex _regex = new Regex("[^0-9.-]+"); //regex that matches disallowed text
    private static bool IsTextAllowed(string text)
    {
        return !_regex.IsMatch(text);
    }
    

    If you want to prevent pasting of incorrect data hook up the DataObject.Pasting event DataObject.Pasting="TextBoxPasting" as shown here (code excerpted):

    // Use the DataObject.Pasting Handler 
    private void TextBoxPasting(object sender, DataObjectPastingEventArgs e)
    {
        if (e.DataObject.GetDataPresent(typeof(String)))
        {
            String text = (String)e.DataObject.GetData(typeof(String));
            if (!IsTextAllowed(text))
            {
                e.CancelCommand();
            }
        }
        else
        {
            e.CancelCommand();
        }
    }
    
    0 讨论(0)
提交回复
热议问题