Number formatting

  • Thread starter Thread starter John S
  • Start date Start date
J

John S

I have created an event handler that is trying to format each number as it
is typed. Example
If the first char is 1 = output is $1.00
second char is 3 = output is $13.00
next is 5 = $135.00
next is 7 = $1,3576.00

Here is my code but I cannot get it to work.

public static void ReturnFormattedNumber(object sender,
System.Windows.Forms.KeyPressEventArgs e){

//KeyPress event

TextBox tb = (TextBox) sender;

int charPosition = tb.SelectionStart;

tb.Text = tb.Text.Substring(tb.SelectionStart + tb.SelectionLength) +

Char.ToUpper(e.KeyChar) +

tb.Text.Substring(0, charPosition);

tb.SelectionLength = 0;

tb.SelectionStart = charPosition;

bool tf =IsNumeric(tb.Text,true);

if(tf==true){

tb.Text=String.Format("{0:C}",tb.Text);

Debug.WriteLine(String.Format("{0:C}",tb.Text));

}

e.Handled=true;

}
 
This sounds more painful than it is: but I remember reading an article about making a numeric-only custom control... Hang on {MSDN search}... eegadd it is in that most stale and worthless of languages -VB- but it should translate to C# easily:

Article is: "Developing Custom Windows Controls Using Visual Basic .NET"

Useful code snippet:

Public Class NumericTextBox
Inherits System.Windows.Forms.TextBox
Protected Overrides Sub OnKeyPress(ByVal e As _
System.Windows.Forms.KeyPressEventArgs)
e.Handled = Not Char.IsDigit(e.KeyChar)
End Sub
End Class

--Richard
 
If you want it to format as they type, this is significantly more
complicated than what you mentioned in your prior post. In this case, I'd
actually recommend you use both KeyPress and TextChanged to handle this and
make sure the caret gets repositioned correctly. Here's a start for you:

private void textBox1_TextChanged(object sender, System.EventArgs e)
{
// Get the current caret position
TextBox tb = (TextBox) sender;
int caretPosition = tb.SelectionStart;

// This just keeps the event from running again when we change the
text below --
// it's a bit of a hack.
if (tb.Tag != null)
return;

// Get the number of non-numeric chars before the caret -- we'll
need this later
// to reposition the caret
int numIndex = StripNonNumerics(tb.Text.Substring(0,
caretPosition)).Length;

// Strip all non-numeric characters out of the text
string stripped = StripNonNumerics(tb.Text);

try
{
// Convert to a double and then back to delimited string in
currency format
string newString = Double.Parse(stripped).ToString("C2");

// Set the text in the field (the Tag is just to prevent an
infinite loop in
// the event handler).
tb.Tag = this;
tb.Text = newString;
tb.Tag = null;

// Reset the caret
int newCaretPosition = GetNumericIndex(newString, numIndex);

tb.SelectionLength = 0;
tb.SelectionStart = newCaretPosition;
}
catch
{
}
}

// Removes all non-numeric characters from the string
private string StripNonNumerics(string s)
{
string stripped = "";

for (int i = 0; i < s.Length; i++)
if (Char.IsDigit(s) || (s == '.'))
stripped += s;

return stripped;
}

// Locates the nth numeric character within a string
private int GetNumericIndex(string s, int numIndex)
{
int numCount = 0;

for (int i = 0; i < s.Length; i++)
if (Char.IsDigit(s) || (s == '.'))
if (++numCount > numIndex) return i;

return s.Length;
}


One thing this code won't do is handle too gracefully is the case when the
user deletes the decimal point character in the text field. This causes the
two 0's after the decimal point to be merged with the digits to its left.
Anyway, I leave you to figure that part out.

Ken
 
Back
Top