Having text inside NumericUpDown control, after the number
Is it possible in WinForms to show a text inside a NumericUpDown control? For example I want to show the value in my numericupdown cont开发者_运维百科rol is micro ampers so it should be like "1 uA".
Thanks.
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
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
}
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();
}
}
}
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.
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.
精彩评论