16

WinFormsでNumericUpDownコントロール内にテキストを表示することは可能ですか?たとえば、numericupdownコントロールの値がマイクロアンペアであることを示したいので、「1uA」のようにする必要があります。

ありがとう。

4

4 に答える 4

30

標準コントロールにそのような機能は組み込まれていません。ただし、クラスから継承し、それに応じて数値をフォーマットするメソッド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

于 2011-05-07T14:12:14.460 に答える
3

CodeGray回答、 ValidateEditTextの失敗に関するFabioのコメント、および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
}
于 2018-11-07T18:11:26.860 に答える
2

これは、接頭辞0xが付いた16進数のNumericUpDownに少なくとも2桁を表示するために使用したものです。コントロールにテキストを配置し、.Net提供フィールドを使用して「デバウンス」の使用を回避しますChangingText

    class HexNumericUpDown2Digits : NumericUpDown
    {
        protected override void UpdateEditText()
        {
            if (Hexadecimal)
            {
                ChangingText = true;
                Text = $"0x{(int)Value:X2}";
            }
            else
            {
                base.UpdateEditText();
            }
        }
    }
于 2019-03-28T20:11:48.070 に答える
1

私は最近この問題に出くわし、CodyGrayの素晴らしい答えを見つけました。私はそれを有利に使用しましたが、最近、接尾辞がまだある場合にテキストが検証に失敗する方法について話している彼の回答に対するコメントの1つに共感しました。私はこれに対しておそらくそれほど専門的ではないクイックフィックスを作成しました。

基本的に、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;
        }
    }

私の答えを改善するか、何かが間違っている場合は私を訂正してください。私はまだ学んでいる独学のプログラマーです。

于 2017-07-01T08:22:07.050 に答える