We help IT Professionals succeed at work.

Format number in TextBox when typing

Mortaza Doulaty
on
Medium Priority
18,006 Views
Last Modified: 2013-12-17
I want to write some code to format the numeric inputs in a TextBox that each three digit is seperated with a comma, like this: 1,648,195 (like using {0:N0} format string)
But I want to format the input in textbox when typing.
I write a little code, but making Backspace and Delete works fine changed to a headache for me!
I want to have a code that does not use any global variable in class level.
My own code is something like this:
private void textBox1_TextChanged(object sender, EventArgs e)
        {
 
            TextBox t = (TextBox)sender;
 
            if (t.Tag!=null && t.Tag.ToString() == "0") return;
            String Text = t.Text;
            int selStart = t.SelectionStart;
            int commaCount_Before = 0;
            int commaCount_After = 0;
            for (int i = 0; i < Text.Length; i++)
            {
                if (Text.Substring(i, 1) == ",")
                {
                    commaCount_Before++;
                }
            }
            Decimal Num;
            Text = Text.Replace(",", "");
            if (Decimal.TryParse(Text, out Num))
            {
                Text = String.Format("{0:N0}", Num);
                t.Text = Text;
            }
            for (int i = 0; i < Text.Length; i++)
            {
                if (Text.Substring(i, 1) == ",")
                {
                    commaCount_After++;
                }
            }
            int diff = (commaCount_After - commaCount_Before);
            if (diff>=0)
            {
                t.SelectionStart = selStart + (commaCount_After - commaCount_Before);
            }
 
        }
 
        private void textBox1_Leave(object sender, EventArgs e)
        {
            String Text = ((TextBox)sender).Text.Replace(",","");
            int Num;
            if (int.TryParse(Text,out Num))
            {
                Text = String.Format("{0:N0}", Num);
                ((TextBox)sender).Text = Text;
            }
            
        }
 
        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            
        }
 
        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            TextBox t = sender as TextBox;
            bool FirstTime = false;
            if (e.KeyCode == Keys.Delete || e.KeyCode == Keys.Back)
            {
                if (t.Text.Contains(",") == true)
                {
                    FirstTime = true;
                }
                else
                {
                    return;
                }
            }
            if (e.KeyCode == Keys.Back)
            {
                int commaCount = 0;
                t.Tag = "0";
                int selStart = t.SelectionStart;
                for (int i = 0; i < selStart; i++)
                {
                    if (t.Text.Substring(i, 1) == ",")
                    {
                        commaCount++;
                    }
                }
                t.Text = t.Text.Replace(",", "");
                selStart -= commaCount;
                if (selStart>=0)
                {
                    t.SelectionStart = selStart;    
                }
                
            }
            else if (e.KeyCode == Keys.Delete)
            {
                int commaCount = 0;
                t.Tag = "0";
                int selStart = t.SelectionStart;
                for (int i = 0; i < selStart; i++)
                {
                    if (t.Text.Substring(i, 1) == ",")
                    {
                        commaCount++;
                    }
                }
                t.Text = t.Text.Replace(",", "");
                selStart += commaCount;
                selStart-=3;
                if (selStart>=0)
                {
                    t.SelectionStart = selStart;
                }
            }
            else
            {
                t.Tag = "";
            }
 
            if (FirstTime)
            {
                e.Handled = true;
                return;
            }
        }

Open in new window

Comment
Watch Question

Author

Commented:
Thanks, but my app is a desktop application (Windows Application), not a web app.

Commented:
how about this?

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            try
            {
                int iKeep = textBox1.SelectionStart-1;
                for (int i=iKeep;i>0;i--)
                    if (textBox1.Text[i] == '.')
                        iKeep -= 1;
 
                textBox1.Text = String.Format("{0:N0}", Convert.ToInt32(textBox1.Text.Replace(".","")));
                for (int i=0;i<iKeep;i++)
                  if (textBox1.Text[i]=='.')
                      iKeep+=1;
          
                textBox1.SelectionStart = iKeep+1;
          }
            catch
            {
                //errorhandling
            }
 
        }
    }

Open in new window

Commented:
ha, dutch version, try this instead ;)
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            try
            {
                int iKeep = textBox1.SelectionStart-1;
                for (int i=iKeep;i>0;i--)
                    if (textBox1.Text[i] == ',')
                        iKeep -= 1;
 
                textBox1.Text = String.Format("{0:N0}", Convert.ToInt32(textBox1.Text.Replace(",","")));
                for (int i=0;i<iKeep;i++)
                  if (textBox1.Text[i]==',')
                      iKeep+=1;
          
                textBox1.SelectionStart = iKeep+1;
          }
            catch
            {
                //errorhandling
            }
 
        }
    }

Open in new window

Author

Commented:
Thanks, there are some minor problems:
1) Suppose that we have entered: 123,456,789
When the cursor is after 7 and you press Backspace, it deletes the 7, but the cursor goes to after 5, instead of 6.
2) Suppose that we have entered: 123,456
The cursor is after 1, you type a digit, the cursor should go after the newly entered digit...
3) Suppose that we have entered: 123,456,789
The cursor is before 7, and we press Delete, the cursor should go to after 6 but doesn't...

Thanks...
Commented:
ok, 1 and 3 are solved by changing a few minor details; 2 i cant reproduce.  (you took out the keydown code?)

 change this line
                for (int i=iKeep;i>0;i--)
to
                for (int i=iKeep;i>=0;i--)

and
                for (int i=0;i<iKeep;i++)
to:
                for (int i=0;i<=iKeep;i++)

 

Author

Commented:
Great thanks for your help. It is 01:30 AM here and I was awake to solve this issue!
Thanks for your help.
About 2, I think I was too sleepy, I can not produce it again :D
Again thanks for your help.
I think your code should work in every situation.

Author

Commented:
There is still one minor thing, before commas when we press Delete
or after commas when we press Backspace, nothing is done...

Commented:
hi, not completely tested but here goes:

    public partial class Form1 : Form
    {
        bool bBack = false;
        bool bDel = false;
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void textBox1_KeyUp(object sender, KeyEventArgs e)
        {
 
        }
 
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            string sDummy = textBox1.Text;
            try
            {
                int iKeep = textBox1.SelectionStart-1;
                for (int i=iKeep;i>=0;i--)
                    if (textBox1.Text[i] == ',')
                        iKeep -= 1;
 
                sDummy = String.Format("{0:N0}", Convert.ToInt32(sDummy.Replace(",","")));
                for (int i=0;i<=iKeep;i++)
                  if (sDummy[i]==',')
                      iKeep+=1;
          
                if ((bDel)&&(iKeep>-1))
                {
                    bDel = false;
                    if ((iKeep+1 < sDummy.Length) && (sDummy[iKeep+1] == ','))
                    {
                        sDummy=sDummy.Remove(iKeep+2, 1);
                    }
                }
                if ((bBack) && (iKeep > -1))
                {
                    bBack = false;
                    if (sDummy[iKeep+1] == ',')
                    {
                        sDummy = sDummy.Remove(iKeep, 1);
                        iKeep = iKeep-1;
                    }
                }
                textBox1.Text = sDummy;
                textBox1.SelectionStart = iKeep+1;
               
 
          }
            catch
            {
                //errorhandling
            }
 
        }
 
        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            bBack = (e.KeyData == Keys.Back);
            bDel = (e.KeyData == Keys.Delete);
            e.Handled = false;
 
        }
    }

Open in new window

Author

Commented:
Thanks for the code.
But the use of variables outside of the event handlers is not welcomed, due the count of textboxes.
Great thanks for your help and patience.

Commented:
lol no problem, it is something i prob. need in the future myself :)

1 more try then:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void textBox1_KeyUp(object sender, KeyEventArgs e)
        {
 
        }
 
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            string sDummy = textBox1.Text;
            try
            {
                int iKeep = textBox1.SelectionStart-1;
                for (int i=iKeep;i>=0;i--)
                    if (textBox1.Text[i] == ',')
                        iKeep -= 1;
 
                sDummy = String.Format("{0:N0}", Convert.ToInt32(sDummy.Replace(",","")));
                for (int i=0;i<=iKeep;i++)
                  if (sDummy[i]==',')
                      iKeep+=1;
          
                textBox1.Text = sDummy;
                textBox1.SelectionStart = iKeep+1;
               
 
          }
            catch
            {
                //errorhandling
            }
 
        }
 
        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (sender is TextBox)
            {
                int i = ((TextBox)sender).SelectionStart;
                if (i>0)
                  if (e.KeyData == Keys.Back)
                    if (((TextBox)sender).Text[i-1] == ',')
                        ((TextBox)sender).SelectionStart -= 1;
                
                if (i<((TextBox)sender).Text.Length)
                  if (e.KeyData == Keys.Delete)
                    if (((TextBox)sender).Text[i] == ',')
                        ((TextBox)sender).SelectionStart += 1;
            }
            e.Handled = false;
 
        }
    }

Open in new window

Author

Commented:
Dear Limbeck, thanks for your effort.
It changed to a nice code ;)

Commented:
ha yes it did didnt it ;)

well enjoy :) and if you find ways to improve it; post the resulting code for future reference.

goodluck on your project

Ed.

Author

Commented:
>>if you find ways to improve it; post the resulting code for future reference.
Certainly...