Formatting numeric data in textbox

A

Andrus

I need to format any decimal value so that it is right aligned, thousands
are separated and shows 2 decimal places always.

I tried code below but this shows number in wrong format, "1 2 ."

How to force TextBox or MaskedTextBox display 12 as 12.00 ?

Andrus.

using System;
using System.Windows.Forms;

class Order
{
public decimal Amount { get; set; }
}

class Form1 : Form
{
static void Main()
{
Application.Run(new Form1());
}

public Form1()
{
Controls.Add(new Button() { Top = 200 });
var mtb = new MaskedTextBox();
mtb.Mask = "9,999.99";
mtb.AsciiOnly = true;
mtb.HidePromptOnLeave = true;
mtb.TextAlign = HorizontalAlignment.Right;
mtb.ValidatingType = typeof(decimal);
var ord = new Order() { Amount = 12 };
mtb.DataBindings.Add("Text", ord, "Amount");
Controls.Add(mtb);
}
}
 
J

jake

Andrus,
The following was written in VS2005; it comes close to your desired
behavior. the difference in here is that when the user starts
entering numbers, the digits start appearing at the lowest order
decimals (cents) and moves to higher order digits as the numbers are
being entered. Much the same way an ATM machine behaves.

For example, if the user enters 2 6 3 8 9, you will see the following
progression:
0.02
0.26
2.63
26.38
263.89

Of course, the text box would still have to be right justified.

If you find the aforementioned behavior acceptable then here is the
code:

private void textBox_TextChanged(object sender, EventArgs e)
{
txtAmount.Text = txtAmount.Text.Replace(",", "");
txtAmount.Text = txtAmount.Text.Replace(".", "");
txtAmount.Text = txtAmount.Text.Replace("$", "");
if (txtAmount.Text.Length > 0)
{
string sContent = txtAmount.Text;
/* pad the number with zeros */
sContent = "000" + sContent;
/* put a decimal point */
sContent = sContent.Substring(0, sContent.Length - 2) + "." +
sContent.Substring(sContent.Length - 2, 2);
/* trim the left side zeros */
for (; sContent.Substring(0, 1) == "0" && sContent.Substring(1, 1) !
= "."; sContent = sContent.Substring(1));
/* get the integer part of the number */
string intPart2 = sContent.Substring(0, sContent.IndexOf("."));
string intPart1= "";
/* reverse the string to make it easier to put thousands separator
(comma) */
for (int i = 0; i < intPart2.Length; i++)
intPart1 += intPart2.Substring(intPart2.Length - i - 1, 1);
/* put the thousands separator */
for (int i = 3; i < intPart1.Length; i += 3)
intPart1 = intPart1.Substring(0, i) + "," + intPart1.Substring(i+
+);
/* reverse the integer part back so we can join it to the number */
string intPart = "";
for (int i = 0; i < intPart1.Length; i++)
intPart += intPart1.Substring(intPart1.Length - i - 1, 1);
sContent = intPart + sContent.Substring(sContent.IndexOf("."));
txtAmount.Text = sContent;
}
}

By the way, this will work with all the editing keys such as
backspace, delete, arrows...etc.

Hope this helps,
jake
 
M

Mihai N.

I need to format any decimal value so that it is right aligned, thousands
are separated and shows 2 decimal places always.

It is good to show the info in the format the user prefers.
That is language/locale speciffic (CultureInfo in the .NET lingo)
So you should use something like ToString("N")
If you are sure you want 2 digits after decimal separator, then use "N2"
 
A

Andrus

Mihai,
It is good to show the info in the format the user prefers.
That is language/locale speciffic (CultureInfo in the .NET lingo)
So you should use something like ToString("N")
If you are sure you want 2 digits after decimal separator, then use "N2"

Thank you.

I need to format numbers when form is initially shown and after user leaves
changed TextBox.
Which TextBox event should be used for this ? Where ToString("N2") call
should be placed ?

Andrus.
 
A

Andrus

Jake,
The following was written in VS2005; it comes close to your desired
behavior. the difference in here is that when the user starts
entering numbers, the digits start appearing at the lowest order
decimals (cents) and moves to higher order digits as the numbers are
being entered. Much the same way an ATM machine behaves.

Thank you.

As demostrated in my sample I need that TextBox shows decimal data in
provided
format (#,###.##) when form is initially opened.
Bound decimal property may contain value with other presicion.

How to force TextBox or MaskedTextbox to format value without editing ?

Andrus.
 
M

Mihai N.

I need to format numbers when form is initially shown and after user leaves
changed TextBox.
Which TextBox event should be used for this ? Where ToString("N2") call
should be placed ?

I personally try to stay away from Mask.
I initialize the fields when I create the form (using ToString),
and I validate them when user tries to submit the data
(using Parse or TryParse)
 
A

Andrus

I personally try to stay away from Mask.
I initialize the fields when I create the form (using ToString),
and I validate them when user tries to submit the data
(using Parse or TryParse)

I do'nt understant this.
In the sample code I posted Textbox is data bound to decimal property Amount
which has value 12
Winforms initializes this TextBox automatically.

How to force Textbox to show 12.00 when form is shown and TextBox does not
receive focus ?

DataGridView column has DefaultCellStyle.Format property for this.
I havent found .Format property when TextBox is not in DataGridView.

Andrus.
 
M

Mihai N.

In the sample code I posted Textbox is data bound to decimal property
Amount which has value 12
Winforms initializes this TextBox automatically.

I am not sure if Winforms uses the CultureInfo for that (to use the proper
decimal/thousand separators).
If it does, then just let Winforms do the work.

Otherwise, you might have to capture the loss of focus and reformat the way
you want.

Personally (as user), I don't care much about stuff being reformated.
If I type .2 and remains like this, I'm ok with it.
But I do care a lot about separators (123,456 means a completely different
thing in Germany vs US)
 
A

Andrus

In the sample code I posted Textbox is data bound to decimal property
I am not sure if Winforms uses the CultureInfo for that (to use the proper
decimal/thousand separators).
If it does, then just let Winforms do the work.

The issue is not related to cultureinfo.
Isse is that it is not possible to show 12 with 2 decimal places when form
is opened.
Otherwise, you might have to capture the loss of focus and reformat the
way
you want.

Personally (as user), I don't care much about stuff being reformated.
If I type .2 and remains like this, I'm ok with it.
But I do care a lot about separators (123,456 means a completely different
thing in Germany vs US)

My issue is that my program calculates product cost etc. using 5 digits
after comma and this must remain.
Users want to see this value with 2 digits after comma and also to enter
this value.
DataGridView DefaultCellStyle has Format property which allows this but
there is no such property when TextBox is placed to form.

Andrus.
 
M

Mihai N.

The issue is not related to cultureinfo.
Not quite. CultureInfo gives you the right decimal separator
(which is a good thing).
Isse is that it is not possible to show 12 with 2 decimal places when form
is opened. ToString("N2")

DataGridView DefaultCellStyle has Format property which allows this but
there is no such property when TextBox is placed to form.
Than you have to do it yourself by calling ToString when the control looses
focus.
 
A

Andrus

Mihai,
Than you have to do it yourself by calling ToString when the control
looses
focus.

When form is initially shown, control does not lose focus.
So there is no place to call ToString().

Andrus.
 
M

Mihai N.

When form is initially shown, control does not lose focus.
So there is no place to call ToString().
Then you might have to do the same at creation,
not only at lose focus.
 
A

Andrus

Mihai,
Then you might have to do the same at creation,
not only at lose focus.

thank you.
I tried code below but TextBox still shows 12
how to force it to display 12.00 ?

Andrus.


using System;
using System.Windows.Forms;

class Order
{
public decimal Amount { get; set; }
}

class Form1 : Form
{
static void Main()
{
Application.Run(new Form1());
}

public Form1()
{
Controls.Add(new Button() { Top = 200 });
var mtb = new TextBox();
mtb.TextAlign = HorizontalAlignment.Right;
var ord = new Order() { Amount = 12 };
mtb.DataBindings.Add("Text", ord, "Amount");
mtb.Text = ord.Amount.ToString("#,###.00");
Controls.Add(mtb);
}
}
 
M

Mihai N.

Ok, forget trying to do it yourself :)
I did not understand you are trying to use binding.
Binding can use a formatter.

Try this:
============

using System;
using System.Windows.Forms;
using System.Globalization;

class Order
{
public decimal Amount { get; set; }
}

class Form1 : Form
{
static void Main()
{
// Application.CurrentCulture; = new CultureInfo(("fr-SW");
Application.Run(new Form1());
}

public Form1()
{
Controls.Add(new Button() { Top = 200 });

var ord = new Order() { Amount = 123456789.7654M };
var mtb = new TextBox();
NumberFormatInfo nf = Application.CurrentCulture.NumberFormat;
mtb.DataBindings.Add("Text", ord, "Amount", true,
DataSourceUpdateMode.OnPropertyChanged,
"<null>", "N2", nf );
Controls.Add(mtb);
}
}
============

To have some fun, try going to "Control Panel" and in "Regional and Language
Options" for to "Formats" tab (first) try changing the "Current Format"
to something like "French (Switzerland)" (you'll get 123'456'789.77)
or "Hindi (India)" (interesting thousand grouping: 12,34,56,789.77)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top