Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
DBase II vs. .Net?
Message
From
18/11/2006 17:11:51
 
 
To
17/11/2006 17:33:16
James Hansen
Canyon Country Consulting
Flagstaff, Arizona, United States
General information
Forum:
ASP.NET
Category:
Forms
Miscellaneous
Thread ID:
01170875
Message ID:
01171017
Views:
16
I haven't used hardly any of the new features of 2.0 yet, so I decided to look at the new MaskedTextBox. Wow ... what a useless piece of garbage ... at least for decimal data, I didn't try using it for anything else just yet. There may be tricks one has to know to get it working correctly, but I haven't researched it at all.

We created our own NumericTextBox sub-class in our 1.1 app (we've ported the app to 2.0, but haven't taken advantage of any new features as of yet). Here's what we've got:

This has been subclassed from our own TextBox subclass, but I think it has everything in it that does the numeric checking and our TextBox subclass is not needed. I don't know for sure though, so test this out just sub-classing from the .NET textbox and if it still doesn't do it correctly, let me know and I can post the code for our TextBox class.
	public class MyNumericTextBox : System.Windows.Forms.TextBox
	{
		#region Declarations
		private int m_DecimalPlaces = 0;
		private decimal m_Maximum = 100;
		private decimal m_Minimum = 0;
		protected char[] AllowedChars = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-'};
		protected string m_FormatString = "##0";
		#endregion

		#region Constructor
		public MyNumericTextBox ()
		{
			this.MaxLength = 3;
			this.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
		}
		#endregion

		#region Methods
		public void SetText(object val)
		{
			if (this.m_Minimum > 0)
			{
				if (val is Decimal)
					this.Text = ((decimal)val).ToString(this.m_FormatString);
			}
			else
			{
				if (val is int)
					this.Text = ((int)val).ToString(this.m_FormatString);
			}
		}
		#endregion

		#region Events
		protected override void FormatHandler(object sender, ConvertEventArgs e)
		{
			if (e.Value == System.DBNull.Value)
				e.Value = (int)0;

			if (e.Value is Decimal && e.DesiredType == typeof(string))
				e.Value = ((decimal)e.Value).ToString(this.m_FormatString);
			else if (e.Value is int && e.DesiredType == typeof(string))
				e.Value = ((int)e.Value).ToString(this.m_FormatString);
		}
		protected override void ParseHandler(object sender, ConvertEventArgs e)
		{
			if (((string)e.Value).Trim().Length == 0)
				e.Value = "0";

			if (e.DesiredType == typeof(decimal))
				e.Value = Decimal.Parse((string)e.Value, System.Globalization.NumberStyles.Any);
			else if (e.DesiredType == typeof(int))
			{
				string[] s = ((string)e.Value).Trim().Split('.');
				e.Value = Decimal.Parse(s[0], System.Globalization.NumberStyles.Any);
			}
		}
		protected override void KeyPressHandler(object sender, KeyPressEventArgs e)
		{
			// Prevent illegal characters
			bool allowed = false;
			for (int i = 0; i < this.AllowedChars.Length; i++) 
			{
				if (e.KeyChar == this.AllowedChars[i])
				{
					allowed = true;
					break;
				}
			}

			// Prevent duplicates of decimal point and minus sign
			if (allowed == false)
				e.Handled = true;
			else if ((e.KeyChar == '.' || e.KeyChar == '-') && this.Text.IndexOf(e.KeyChar) >= 0)
				e.Handled = true;

			// Prevent too many digits on either side of decimal point
			if (this.m_DecimalPlaces > 0)
			{
			}
		}
		protected override void ValidatingHandler(object sender, CancelEventArgs e)
		{
			if (this.Text.Trim().Length == 0)
				return;

			try
			{
				decimal test = Decimal.Parse(this.Text);
				if (test > this.m_Maximum || test < this.m_Minimum)
				{
					string message = "The value for this field must be between " +
						this.m_Maximum.ToString() + " and " + this.m_Minimum.ToString() + "!";
					string caption = "Value out of range";
					MessageBox.Show(message, caption, MessageBoxButtons.OK, MessageBoxIcon.Error);

					e.Cancel = true;
				}
			}
			catch (Exception ex)
			{
				System.Diagnostics.Debug.WriteLine(ex.Message);
			}
		}
		#endregion

		#region Properties
		[Description("The number of digits to display after the decimal.")]
		[DefaultValue(0)]
		public int DecimalPlaces
		{
			get {return this.m_DecimalPlaces;}
			set
			{
				this.m_DecimalPlaces = value;

				// Create the AllowedChars array for the KeyPress event handler
				if (value > 0 && this.m_Minimum < 0)
					this.AllowedChars = new char[] {(char)Keys.Back, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.', '-'};
				else if (value > 0)
					this.AllowedChars = new char[] {(char)Keys.Back, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.'};
				else if (this.m_Minimum < 0)
					this.AllowedChars = new char[] {(char)Keys.Back, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-'};
				else
					this.AllowedChars = new char[] {(char)Keys.Back, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};

				// Create the FormatString property value
				string[] format = this.m_FormatString.Split(new char[] {'.'}, 2);
				if (value > 0)
				{
					string s = new string('0', value);
					this.m_FormatString = format[0] + "." + s;
				}
				else
					this.m_FormatString = format[0];

				this.MaxLength = this.m_FormatString.Length;
				if (this.m_Minimum < 0 && this.m_Minimum.ToString().Length > this.m_Maximum.ToString().Length)
					this.MaxLength++;
			}
		}
		[Description("The maximum value allowed in the field.")]
		[DefaultValue(100)]
		public decimal Maximum
		{
			get {return this.m_Maximum;}
			set
			{
				if (value < this.m_Minimum)
					return;

				this.m_Maximum = value;

				// Create the first half of the FormatString property
				this.MaxLength = value.ToString().Length;
				int max = this.m_Minimum.ToString().Length;
				if (this.m_Minimum < 0 && max > this.MaxLength)
					this.MaxLength = max;

				if (this.MaxLength > 2 && value.ToString().Length < this.m_Minimum.ToString().Length)
					this.m_FormatString = new string('#', this.MaxLength - 2) + "0";
				else if (this.MaxLength > 1)
					this.m_FormatString = new string('#', this.MaxLength - 1) + "0";
				else
					this.m_FormatString = "0";

//				if (this.m_Minimum < 0)
//					this.m_FormatString = "-" + this.m_FormatString;

				// Finally, create the formatting
				this.DecimalPlaces = this.m_DecimalPlaces;
			}
		}
		[Description("The minimum value allowed in the field.")]
		[DefaultValue(0)]
		public decimal Minimum
		{
			get {return this.m_Minimum;}
			set
			{
				if (value > this.m_Maximum)
					return;
				
				this.m_Minimum = value;
				this.Maximum = this.m_Maximum;
			}
		}
//		[Description("The string to use with ToString to format.")]
//		[DefaultValue("##0")]
//		public string FormatString
//		{
//			get {return this.m_FormatString;}
//			set {this.m_FormatString = value;}
//		}
		#endregion
	}
~~Bonnie


>Just when I'm really getting to like .Net, C# and some of the really cool things I can do like that marvelous free charting tool, I've got to go and try to input decimal numbers.
>
>Warning: Flame on!
>
>I've just spent several hours searching for a control to do decimal input as nicely as dBase II with no luck!
>
>If I have a format like ##0.0 and I type 10.1, I expect to not have to position the cursor after the first blank space before typing! This is not unreasonable. I could do it in Fortran IV inputting from a teletype, for Pete's sake! In FoxBase I could type "10" and when I hit the decimal point the cursor would hop over to where it belonged and I could continue typing the fractional part. And I didn't have to write three or four event handlers to get the job done either!
>
>Comeon! Somebody has got to have done this right in a subclassed control?
>
>Is there any word yet? Will the next version of .Net be as good as dBase II?
>
>Flame off
Bonnie Berent DeWitt
NET/C# MVP since 2003

http://geek-goddess-bonnie.blogspot.com
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform