Having text inside NumericUpDown control, after the number

前端 未结 4 2024
自闭症患者
自闭症患者 2020-12-09 04:39

Is it possible in WinForms to show a text inside a NumericUpDown control? For example I want to show the value in my numericupdown control is micro ampers so it should be li

4条回答
  •  情书的邮戳
    2020-12-09 05:21

    Using CodeGray's answer, Fabio's comment about it failing ValidateEditText, and the NumericUpDown documentation I've come up with a simple NumericUpDownWithUnit component. You can copy/paste as is:

    using System;
    using System.Globalization;
    using System.Text.RegularExpressions;
    using System.Windows.Forms;
    
    public class NumericUpDownWithUnit : NumericUpDown
    {
        #region| Fields |
    
        private string unit = null;
        private bool unitFirst = true;
    
        #endregion
    
        #region| Properties |
    
        public string Unit
        {
            get => unit;
            set
            {
                unit = value;
    
                UpdateEditText();
            }
        }
    
        public bool UnitFirst
        {
            get => unitFirst;
            set
            {
                unitFirst = value;
    
                UpdateEditText();
            }
        }
    
        #endregion
    
        #region| Methods |
    
        /// 
        /// Method called when updating the numeric updown text.
        /// 
        protected override void UpdateEditText()
        {
            // If there is a unit we handle it ourselfs, if there is not we leave it to the base class.
            if (Unit != null && Unit != string.Empty)
            {
                if (UnitFirst)
                {
                    Text = $"({Unit}) {Value}";
                }
                else
                {
                    Text = $"{Value} ({Unit})";
                }
            }
            else
            {
                base.UpdateEditText();
            }
        }
    
        /// 
        /// Validate method called before actually updating the text.
        /// This is exactly the same as the base class but it will use the new ParseEditText from this class instead.
        /// 
        protected override void ValidateEditText()
        {
            // See if the edit text parses to a valid decimal considering the label unit
            ParseEditText();
            UpdateEditText();
        }
    
        /// 
        /// Converts the text displayed in the up-down control to a numeric value and evaluates it.
        /// 
        protected new void ParseEditText()
        {
            try
            {
                // The only difference of this methods to the base one is that text is replaced directly
                // with the property Text instead of using the regex.
                // We now that the only characters that may be on the textbox are from the unit we provide.
                // because the NumericUpDown handles invalid input from user for us.
                // This is where the magic happens. This regex will match all characters from the unit
                // (so your unit cannot have numbers). You can change this regex to fill your needs
                var regex = new Regex($@"[^(?!{Unit} )]+");
                var match = regex.Match(Text);
    
                if (match.Success)
                {
                    var text = match.Value;
    
                    // VSWhidbey 173332: Verify that the user is not starting the string with a "-"
                    // before attempting to set the Value property since a "-" is a valid character with
                    // which to start a string representing a negative number.
                    if (!string.IsNullOrEmpty(text) && !(text.Length == 1 && text == "-"))
                    {
                        if (Hexadecimal)
                        {
                            Value = Constrain(Convert.ToDecimal(Convert.ToInt32(Text, 16)));
                        }
                        else
                        {
                            Value = Constrain(Decimal.Parse(text, CultureInfo.CurrentCulture));
                        }
                    }
                }
            }
            catch
            {
                // Leave value as it is
            }
            finally
            {
                UserEdit = false;
            }
        }
    
        /// 
        /// Returns the provided value constrained to be within the min and max.
        /// This is exactly the same as the one in base class (which is private so we can't directly use it).
        /// 
        private decimal Constrain(decimal value)
        {
            if (value < Minimum)
            {
                value = Minimum;
            }
    
            if (value > Maximum)
            {
                value = Maximum;
            }
    
            return value;
        }
    
        #endregion
    }
    

提交回复
热议问题