【问题标题】:Having text inside NumericUpDown control, after the number在数字之后的 NumericUpDown 控件中包含文本
【发布时间】:2011-05-07 13:45:54
【问题描述】:

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

谢谢。

【问题讨论】:

  • 控件旁边的标签怎么样?
  • 嗯,这是可能的,但我想把它放在控件本身。
  • 您可以尝试在控件上放置一个标签,否则我想不出一个属性来将字符串附加到 num-up-down 的末尾。
  • 绝对不要试图在控件上放置标签。这将很难做到正确,并成为你身边永远的眼中钉。控件侧面的标签(在表单本身上)通常是一个足够好的解决方案。如果您需要更大的枪,请参阅下面的答案。

标签: c# .net winforms string numericupdown


【解决方案1】:

标准控件中没有内置这样的功能。但是,通过创建一个继承自 NumericUpDown 类并覆盖 UpdateEditText method 以相应地格式化数字的自定义控件来添加它是相当容易的。

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

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 unit measure

【讨论】:

  • @greg 我不知道。但是对于任何 .NET 开发人员来说,VB.NET 和 C# 应该同样易于阅读。如果失败了,总会有自动翻译器。
  • 刚遇到这个,效果很好。我添加了一个属性,并且在设计器中可见,但由于某种原因,附加的文本没有显示在设计器中。一个小问题,它工作正常,但有人有关于如何让这个可见的任何提示吗?
  • 很可能,UpdateEditText 函数从未在设计器中调用。这并不是特别不寻常。设计器的目的只是让您预览事物的外观。它不应该是功能齐全的。很难想象为什么在设计时看到这一点至关重要。按运行即可查看。
  • 这样很好,但是编辑文本的时候会出现问题,因为ValidateEditText()的默认实现如果文本中有后缀就会失败。您还必须覆盖 ValidateEditText() 以将文本转换为数值
【解决方案2】:

使用CodeGray's 回答,Fabio's 评论它失败 ValidateEditText 和 NumericUpDown documentation 我想出了一个简单的 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
}

【讨论】:

    【解决方案3】:

    这是我用来显示至少 2 位以 0x 为前缀的十六进制 NumericUpDown 的数字。 它将文本放在控件中,并通过使用提供的 .Net 避免使用“去抖动” 字段ChangingText

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

    【讨论】:

    • 感谢您提出一个 9 年前的问题!
    【解决方案4】:

    我最近偶然发现了这个问题,发现 Cody Gray 的答案很棒。我利用它来发挥自己的优势,但最近在他的回答中与一位 cmets 产生了共鸣,他谈到如果后缀仍然存在,文本将如何验证失败。我为此创建了一个可能不太专业的快速修复程序。

    基本上,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;
            }
        }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-15
      • 1970-01-01
      • 2016-10-05
      • 1970-01-01
      相关资源
      最近更新 更多