Numeric Data Entry in WPF

前端 未结 17 2512
情话喂你
情话喂你 2020-12-02 05:38

How are you handling the entry of numeric values in WPF applications?

Without a NumericUpDown control, I\'ve been using a TextBox and handling its PreviewKeyDown eve

相关标签:
17条回答
  • 2020-12-02 05:58

    Combining the ideas from a few of these answers, I have created a NumericTextBox that

    • Handles decimals
    • Does some basic validation to ensure any entered '-' or '.' is valid
    • Handles pasted values

    Please feel free to update if you can think of any other logic that should be included.

    public class NumericTextBox : TextBox
    {
        public NumericTextBox()
        {
            DataObject.AddPastingHandler(this, OnPaste);
        }
    
        private void OnPaste(object sender, DataObjectPastingEventArgs dataObjectPastingEventArgs)
        {
            var isText = dataObjectPastingEventArgs.SourceDataObject.GetDataPresent(System.Windows.DataFormats.Text, true);
    
            if (isText)
            {
                var text = dataObjectPastingEventArgs.SourceDataObject.GetData(DataFormats.Text) as string;
                if (IsTextValid(text))
                {
                    return;
                }
            }
    
            dataObjectPastingEventArgs.CancelCommand();
        }
    
        private bool IsTextValid(string enteredText)
        {
            if (!enteredText.All(c => Char.IsNumber(c) || c == '.' || c == '-'))
            {
                return false;
            }
    
            //We only validation against unselected text since the selected text will be replaced by the entered text
            var unselectedText = this.Text.Remove(SelectionStart, SelectionLength);
    
            if (enteredText == "." && unselectedText.Contains("."))
            {
                return false;
            }
    
            if (enteredText == "-" && unselectedText.Length > 0)
            {
                return false;
            }
    
            return true;
        }
    
        protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e)
        {
            e.Handled = !IsTextValid(e.Text);
            base.OnPreviewTextInput(e);
        }
    }
    
    0 讨论(0)
  • 2020-12-02 05:59

    How about:

    protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e)
    {
        e.Handled = !AreAllValidNumericChars(e.Text);
        base.OnPreviewTextInput(e);
    }
    
    private bool AreAllValidNumericChars(string str)
    {
        foreach(char c in str)
        {
            if(!Char.IsNumber(c)) return false;
        }
    
        return true;
    }
    
    0 讨论(0)
  • 2020-12-02 06:03

    Call me crazy, but why not put plus and minus buttons at either side of the TextBox control and simply prevent the TextBox from receiving cursor focus, thereby creating your own cheap NumericUpDown control?

    0 讨论(0)
  • 2020-12-02 06:04

    I use a custom ValidationRule to check if text is numeric.

    public class DoubleValidation : ValidationRule
    {
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            if (value is string)
            {
                double number;
                if (!Double.TryParse((value as string), out number))
                    return new ValidationResult(false, "Please enter a valid number");
            }
    
            return ValidationResult.ValidResult;
        }
    

    Then when I bind a TextBox to a numeric property, I add the new custom class to the Binding.ValidationRules collection. In the example below the validation rule is checked everytime the TextBox.Text changes.

    <TextBox>
        <TextBox.Text>
            <Binding Path="MyNumericProperty" UpdateSourceTrigger="PropertyChanged">
                <Binding.ValidationRules>
                    <local:DoubleValidation/>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
    
    0 讨论(0)
  • 2020-12-02 06:05

    This is how I do it. It uses a regular expression to check if the text that will be in the box is numeric or not.

    Regex NumEx = new Regex(@"^-?\d*\.?\d*$");
    
    private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
    {
        if (sender is TextBox)
        {
            string text = (sender as TextBox).Text + e.Text;
            e.Handled = !NumEx.IsMatch(text);
        }
        else
            throw new NotImplementedException("TextBox_PreviewTextInput Can only Handle TextBoxes");
    }
    

    There is now a much better way to do this in WPF and Silverlight. If your control is bound to a property, all you have to do is change your binding statement a bit. Use the following for your binding:

    <TextBox Text="{Binding Number, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}"/>
    

    Note that you can use this on custom properties too, all you have to do is throw an exception if the value in the box is invalid and the control will get highlighted with a red border. If you click on the upper right of the red border then the exception message will pop up.

    0 讨论(0)
  • 2020-12-02 06:05
    void PreviewTextInputHandler(object sender, TextCompositionEventArgs e)
    {
        string sVal = e.Text;
        int val = 0;
    
        if (sVal != null && sVal.Length > 0)
        {
            if (int.TryParse(sVal, out val))
            {
                e.Handled = false;
            }
            else
            {
                e.Handled = true;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题