在 NumericUpDown 控件内的数字后面有文本

发布于 2024-11-06 07:22:45 字数 103 浏览 5 评论 0原文

WinForms 中是否可以在 NumericUpDown 控件内显示文本?例如,我想显示我的 numericupdown 控件中的值是微安,所以它应该像“1 uA”。

谢谢。

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 like "1 uA".

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

雪化雨蝶 2024-11-13 07:22:45

标准控件中没有内置此类功能。但是,通过创建一个继承自 NumericUpDown 类并覆盖 UpdateEditText 方法 相应地设置数字格式。

例如,您可能有以下类定义:

public class NumericUpDownEx : NumericUpDown
{
    public NumericUpDownEx()
    {
    }

    protected override void UpdateEditText()
    {
        // Append the units to the end of the numeric value
        this.Text = this.Value + " uA";
    }
}

或者,要获得更完整的实现,请参阅此示例项目: NumericUpDown with单位度量

There's no such functionality built into the standard control. However, it's fairly easy added by creating a custom control that inherits from the NumericUpDown class and overrides the UpdateEditText method to format the number accordingly.

For example, you might have the following class definition:

public class NumericUpDownEx : NumericUpDown
{
    public NumericUpDownEx()
    {
    }

    protected override void UpdateEditText()
    {
        // Append the units to the end of the numeric value
        this.Text = this.Value + " uA";
    }
}

Or, for a more complete implementation, see this sample project: NumericUpDown with unit measure

舟遥客 2024-11-13 07:22:45

使用CodeGray的答案,Fabio的< /a> 关于 ValidateEditText 失败的评论,以及 NumericUpDown 文档 我已经找到了使用简单的 NumericUpDownWithUnit 组件。您可以按原样复制/粘贴:

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 |

    /// <summary>
    /// Method called when updating the numeric updown text.
    /// </summary>
    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();
        }
    }

    /// <summary>
    /// 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.
    /// </summary>
    protected override void ValidateEditText()
    {
        // See if the edit text parses to a valid decimal considering the label unit
        ParseEditText();
        UpdateEditText();
    }

    /// <summary>
    /// Converts the text displayed in the up-down control to a numeric value and evaluates it.
    /// </summary>
    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;
        }
    }

    /// </summary>
    /// 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).
    /// </summary>
    private decimal Constrain(decimal value)
    {
        if (value < Minimum)
        {
            value = Minimum;
        }

        if (value > Maximum)
        {
            value = Maximum;
        }

        return value;
    }

    #endregion
}

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 |

    /// <summary>
    /// Method called when updating the numeric updown text.
    /// </summary>
    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();
        }
    }

    /// <summary>
    /// 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.
    /// </summary>
    protected override void ValidateEditText()
    {
        // See if the edit text parses to a valid decimal considering the label unit
        ParseEditText();
        UpdateEditText();
    }

    /// <summary>
    /// Converts the text displayed in the up-down control to a numeric value and evaluates it.
    /// </summary>
    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;
        }
    }

    /// </summary>
    /// 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).
    /// </summary>
    private decimal Constrain(decimal value)
    {
        if (value < Minimum)
        {
            value = Minimum;
        }

        if (value > Maximum)
        {
            value = Maximum;
        }

        return value;
    }

    #endregion
}
相守太难 2024-11-13 07:22:45

这是我用来显示前缀为 0x 的至少 2 位十六进制 NumericUpDown 的方法。
它将文本放入控件中,并通过使用 .Net 提供的方法避免使用“debounce”
字段更改文本

    class HexNumericUpDown2Digits : NumericUpDown
    {
        protected override void UpdateEditText()
        {
            if (Hexadecimal)
            {
                ChangingText = true;
                Text = $"0x{(int)Value:X2}";
            }
            else
            {
                base.UpdateEditText();
            }
        }
    }

Here's what I used for showing at least 2 digits for a hexadecimal NumericUpDown that are prefixed by 0x.
It puts text in the control and avoids using "debounce" by using the .Net provided
field ChangingText

    class HexNumericUpDown2Digits : NumericUpDown
    {
        protected override void UpdateEditText()
        {
            if (Hexadecimal)
            {
                ChangingText = true;
                Text = $"0x{(int)Value:X2}";
            }
            else
            {
                base.UpdateEditText();
            }
        }
    }
吃颗糖壮壮胆 2024-11-13 07:22:45

我最近偶然发现了这个问题,并找到了 Cody Gray 的精彩答案。我利用它来发挥自己的优势,但最近对他的答案中的一条评论产生了共鸣,其中一条评论谈到,如果后缀仍然存在,文本将如何验证失败。我为此创建了一个可能不太专业的快速解决方案。

基本上,this.Text 字段是读取数字的。

一旦找到数字,它们就会被放入 this.Text 中,但是需要进行去抖动或任何您想要调用的内容,以确保我们不会创建堆栈溢出 。

一旦只有数字的新文本进入,就会调用正常的 ParseEditText();UpdateEditText(); 来完成该过程。

这不是最资源友好或最有效的解决方案,但当今大多数现代计算机应该完全可以满足这一要求。

您还会注意到,我创建了一个用于更改后缀的属性,只是为了更方便地在编辑器中使用。

public class NumericUpDownUnit : System.Windows.Forms.NumericUpDown
    {

        public string Suffix{ get; set; }

        private bool Debounce = false;

        public NumericUpDownUnit()
        {

        }

        protected override void ValidateEditText()
        {
            if (!Debounce) //I had to use a debouncer because any time you update the 'this.Text' field it calls this method.
            {
                Debounce = true; //Make sure we don't create a stack overflow.

                string tempText = this.Text; //Get the text that was put into the box.
                string numbers = ""; //For holding the numbers we find.

                foreach (char item in tempText) //Implement whatever check wizardry you like here using 'tempText' string.
                {
                    if (Char.IsDigit(item))
                    {
                        numbers += item;
                    }
                    else
                    {
                        break;
                    }
                }

                decimal actualNum = Decimal.Parse(numbers, System.Globalization.NumberStyles.AllowLeadingSign);
                if (actualNum > this.Maximum) //Make sure our number is within min/max
                    this.Value = this.Maximum;
                else if (actualNum < this.Minimum)
                    this.Value = this.Minimum;
                else
                    this.Value = actualNum; 

                ParseEditText(); //Carry on with the normal checks.
                UpdateEditText();

                Debounce = false;
            }

        }

        protected override void UpdateEditText()
        {
            // Append the units to the end of the numeric value
            this.Text = this.Value + Suffix;
        }
    }

如果有问题,请随时改进我的答案或纠正我,我是一个自学成才的程序员,仍在学习。

I recently stumbled across this issue and found Cody Gray's awesome answer. I used it to my advantage but recently resonated with one of the comments on his answer talking about how the text will fail validation if the suffix is still there. I've created a probably not-so-professional quick fix for this.

Basically the this.Text field is read for numbers.

Once the numbers are found they are put into this.Text, but a debounce or whatever you want to call it is needed to make sure we don't create a stack overflow.

Once the new text with only number is in, the normal ParseEditText(); and UpdateEditText(); are called to complete the process.

This isn't the most resource friendly or efficient solution, but most modern computers today should be perfectly fine with that.

Also you'll notice I've created a property for changing the suffix just for easier use in editor.

public class NumericUpDownUnit : System.Windows.Forms.NumericUpDown
    {

        public string Suffix{ get; set; }

        private bool Debounce = false;

        public NumericUpDownUnit()
        {

        }

        protected override void ValidateEditText()
        {
            if (!Debounce) //I had to use a debouncer because any time you update the 'this.Text' field it calls this method.
            {
                Debounce = true; //Make sure we don't create a stack overflow.

                string tempText = this.Text; //Get the text that was put into the box.
                string numbers = ""; //For holding the numbers we find.

                foreach (char item in tempText) //Implement whatever check wizardry you like here using 'tempText' string.
                {
                    if (Char.IsDigit(item))
                    {
                        numbers += item;
                    }
                    else
                    {
                        break;
                    }
                }

                decimal actualNum = Decimal.Parse(numbers, System.Globalization.NumberStyles.AllowLeadingSign);
                if (actualNum > this.Maximum) //Make sure our number is within min/max
                    this.Value = this.Maximum;
                else if (actualNum < this.Minimum)
                    this.Value = this.Minimum;
                else
                    this.Value = actualNum; 

                ParseEditText(); //Carry on with the normal checks.
                UpdateEditText();

                Debounce = false;
            }

        }

        protected override void UpdateEditText()
        {
            // Append the units to the end of the numeric value
            this.Text = this.Value + Suffix;
        }
    }

Please feel free to better my answer or correct me if something is wrong, I'm a self-taught programmer still learning.

吻风 2024-11-13 07:22:45

您的操作在对象发生更改后开始,您必须从属性部分双击 ValueChanged。
在代码中执行此操作后,您可以看到此代码:

private void numericUpDownMounth_ValueChanged(object sender, EventArgs e)
{
   // Body
}

在 //Body 端,您可以编写代码和控制器。正如其他人所说。

your action start after change on you Object, well you have to Double Click on ValueChanged from properties part.
After this Action In Code You Can See This Code:

private void numericUpDownMounth_ValueChanged(object sender, EventArgs e)
{
   // Body
}

In //Body side you can write your Code and Your Controller. As Others person said.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文