c#.net force textbox validation

michael gamble 1 Reputation point
2022-11-18T17:40:51.92+00:00

I couldn't find a clear solution to this objective so this is my first MSDN post ever!

This works flawlessly when a user pastes from the clipboard:

    private void txtScanEmpDevice3_KeyUp(object sender, KeyEventArgs e)  
    {  
        if (e.KeyCode == Keys.V && e.Modifiers == Keys.Control)  
        {  
            CancelEventArgs e2 = new CancelEventArgs();  
            txtScanEmpDevice3_Validating(sender, e2);  
            if(lblErrorMessage.Text == String.Empty)  
                txtScanEmpDevice3_Validated(sender, e2);  
        }  
    }  
Developer technologies C#
{count} votes

2 answers

Sort by: Most helpful
  1. Michael Taylor 60,161 Reputation points
    2022-11-18T19:38:57.66+00:00

    What is your question? Are you trying to do input validation on a textbox? If so then that is done in Winforms using the Validating event. That event is triggered when a control loses focus and the control gaining focus has CausesValidation set to true (which is the default) as discussed here.

    Note that you should not be calling the event handlers directly in your code. This is non-standard, especially since you aren't handling the validating event correctly in your code. If you need to validate a control then tell the parent control/form to validate the children again. This is a limitation of Winforms validation because you cannot change focus while inside the event you're handling and winforms works based upon focus change.

    Note that a better approach, instead of handling key up, might be to use the TextChanged event. This is raised when the text changes for any reason. The downside is that it gets called for every character typed. The issue with your KeyUp handler is that it is only handling 1 possible way to paste data into a textbox. There are other ways and your code isn't handling such as Shift+Insert (IIRC) and mouse context menu.


  2. Karen Payne MVP 35,586 Reputation points Volunteer Moderator
    2022-11-18T19:46:55.797+00:00

    If you want a TextBox that is numeric only that does not permit pasting from the Windows clipboard try the following. Use integer, Decimal or Double properties to get a specific type and hasValue to see if there is a value. Another option is too use FluentValidation for post validation.

    public class NumericTextBox : TextBox  
    {  
        private readonly char _decimalSeparator =  
            CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator[0];  
      
        public NumericTextBox()  
        {  
            TextAlign = HorizontalAlignment.Right;  
        }  
      
        protected override void OnKeyPress(KeyPressEventArgs e)  
        {  
      
            if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && e.KeyChar != _decimalSeparator)  
            {  
                e.Handled = true;  
            }  
      
            if (e.KeyChar == _decimalSeparator && Text.IndexOf(_decimalSeparator) > -1)  
            {  
                e.Handled = true;  
            }  
      
            base.OnKeyPress(e);  
      
        }  
      
        [Browsable(false)]  
        public int Integer => int.TryParse(Text, out var value) ? value : 0;  
        [Browsable(false)]  
        public decimal Decimal => decimal.TryParse(Text, out var value) ? value : 0;  
        public double Double => double.TryParse(Text, out var value) ? value : 0;  
      
        public bool HasValue() => !string.IsNullOrWhiteSpace(Text);  
      
        int WM_PASTE = 0x0302;  
        protected override void WndProc(ref Message message)  
        {  
            if (message.Msg == WM_PASTE)  
            {  
                var clipboardData = Clipboard.GetDataObject();  
                var input = (string)clipboardData?.GetData(typeof(string));  
                int count = 0;  
      
                foreach (var c in input)  
                {  
                    if (c == _decimalSeparator)  
                    {  
                        count++;  
                        if (count > 1)  
                        {  
                            return;  
                        }  
                    }  
                }  
      
                foreach (var character in input)  
                {  
      
                    if (!char.IsControl(character) && !char.IsDigit(character) && character != _decimalSeparator)  
                    {  
                        message.Result = (IntPtr)0;  
                        return;  
                    }  
      
                }  
            }  
      
            base.WndProc(ref message);  
      
        }  
    }  
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.