How do I make a textbox that only accepts numbers?

后端 未结 30 2177
梦如初夏
梦如初夏 2020-11-21 06:05

I have a windows forms app with a textbox control that I want to only accept integer values. In the past I\'ve done this kind of validation by overloading the KeyPress event

30条回答
  •  甜味超标
    2020-11-21 06:57

    It seems like many of the current answers to this question are manually parsing the input text. If you're looking for a specific built-in numeric type (e.g. int or double), why not just delegate the work to that type's TryParse method? For example:

    public class IntTextBox : TextBox
    {
        string PreviousText = "";
        int BackingResult;
    
        public IntTextBox()
        {
            TextChanged += IntTextBox_TextChanged;
        }
    
        public bool HasResult { get; private set; }
    
        public int Result
        {
            get
            {
                return HasResult ? BackingResult : default(int);
            }
        }
    
        void IntTextBox_TextChanged(object sender, EventArgs e)
        {
            HasResult = int.TryParse(Text, out BackingResult);
    
            if (HasResult || string.IsNullOrEmpty(Text))
            {
                // Commit
                PreviousText = Text;
            }
            else
            {
                // Revert
                var changeOffset = Text.Length - PreviousText.Length;
                var previousSelectionStart =
                    Math.Max(0, SelectionStart - changeOffset);
    
                Text = PreviousText;
                SelectionStart = previousSelectionStart;
            }
        }
    }
    

    If you want something more generic but still compatible with Visual Studio's Designer:

    public class ParsableTextBox : TextBox
    {
        TryParser BackingTryParse;
        string PreviousText = "";
        object BackingResult;
    
        public ParsableTextBox()
            : this(null)
        {
        }
    
        public ParsableTextBox(TryParser tryParse)
        {
            TryParse = tryParse;
    
            TextChanged += ParsableTextBox_TextChanged;
        }
    
        public delegate bool TryParser(string text, out object result);
    
        public TryParser TryParse
        {
            set
            {
                Enabled = !(ReadOnly = value == null);
    
                BackingTryParse = value;
            }
        }
    
        public bool HasResult { get; private set; }
    
        public object Result
        {
            get
            {
                return GetResult();
            }
        }
    
        public T GetResult()
        {
            return HasResult ? (T)BackingResult : default(T);
        }
    
        void ParsableTextBox_TextChanged(object sender, EventArgs e)
        {
            if (BackingTryParse != null)
            {
                HasResult = BackingTryParse(Text, out BackingResult);
            }
    
            if (HasResult || string.IsNullOrEmpty(Text))
            {
                // Commit
                PreviousText = Text;
            }
            else
            {
                // Revert
                var changeOffset = Text.Length - PreviousText.Length;
                var previousSelectionStart =
                    Math.Max(0, SelectionStart - changeOffset);
    
                Text = PreviousText;
                SelectionStart = previousSelectionStart;
            }
        }
    }
    
    
    

    And finally, if you want something fully generic and don't care about Designer support:

    public class ParsableTextBox : TextBox
    {
        TryParser BackingTryParse;
        string PreviousText;
        T BackingResult;
    
        public ParsableTextBox()
            : this(null)
        {
        }
    
        public ParsableTextBox(TryParser tryParse)
        {
            TryParse = tryParse;
    
            TextChanged += ParsableTextBox_TextChanged;
        }
    
        public delegate bool TryParser(string text, out T result);
    
        public TryParser TryParse
        {
            set
            {
                Enabled = !(ReadOnly = value == null);
    
                BackingTryParse = value;
            }
        }
    
        public bool HasResult { get; private set; }
    
        public T Result
        {
            get
            {
                return HasResult ? BackingResult : default(T);
            }
        }
    
        void ParsableTextBox_TextChanged(object sender, EventArgs e)
        {
            if (BackingTryParse != null)
            {
                HasResult = BackingTryParse(Text, out BackingResult);
            }
    
            if (HasResult || string.IsNullOrEmpty(Text))
            {
                // Commit
                PreviousText = Text;
            }
            else
            {
                // Revert
                var changeOffset = Text.Length - PreviousText.Length;
                var previousSelectionStart =
                    Math.Max(0, SelectionStart - changeOffset);
    
                Text = PreviousText;
                SelectionStart = previousSelectionStart;
            }
        }
    }
    

    提交回复
    热议问题