Currency textbox - textbox de saisie de montant.

Soyez le premier à donner votre avis sur cette source.

Snippet vu 16 510 fois - Téléchargée 26 fois

Contenu du snippet

Petite classe permettant la saisie de montant en respectant les contraintes spécifiques liées aux cultures. (Symbol, nombres de décimal)

Source / Exemple :


#region Using
using System;
using System.Windows.Forms;
using System.Globalization;
using System.Drawing;
#endregion Using

namespace CS.TextBoxes
{

	[ToolboxBitmap(typeof(TextBox))]
	/// <summary>
	/// Provides a control allowing typing only currency values. 
	/// This control supports Culture-specific constraints.
	/// </summary>
	public class CurrencyTextBox : TextBox
	{
		#region Fields
		private CultureInfo _culture = System.Globalization.CultureInfo.CurrentUICulture;
		private int _digitsCount = System.Globalization.CultureInfo.CurrentUICulture.NumberFormat.CurrencyDecimalDigits;
		private string separator;
		private bool overridesCulture;
		#endregion Fields

		#region Constructors
		/// <summary>
		/// Initialiazes a new instance of <see cref="CurrencyTextBox"/>.
		/// </summary>
		public CurrencyTextBox() 
		{
			separator = _culture.NumberFormat.CurrencyDecimalSeparator;
		}

		#endregion Constructors

		#region Key events
		protected override void OnKeyPress(KeyPressEventArgs e)
		{
			int sepIndex = this.Text.IndexOf(separator);
			double val = TryParseCurrency(this.Text, !overridesCulture);
			int digits = CountDigits();

			if (char.IsNumber(e.KeyChar) || char.IsControl(e.KeyChar))
			{
				if (digits >= _digitsCount && SelectionStart > sepIndex + digits) //we have not reached the max digits
				{
					e.Handled = true;
				}
				else
				{
					if (char.IsNumber((char)e.KeyChar) &&  val == 0)
					{
						this.Text = e.KeyChar.ToString(_culture);
						this.SelectionStart += 1;
						e.Handled = true;
					}
					else //Value was not 0
						base.OnKeyPress(e);
				}
			}
			else 
			{
				//We entered the separator char
				if (separator.StartsWith(e.KeyChar.ToString(_culture)))
					this.SelectionStart = this.Text.IndexOf(separator) + 1;

					//We entered the negative char
				else if (e.KeyChar == '-')
					this.Text = (-val).ToString(_culture);
				
				e.Handled = true;
			}
			
		}

		protected override void OnTextChanged(EventArgs e)
		{
			base.OnTextChanged(e);
			int cursorPos = this.SelectionStart;
			
			if (cursorPos < 0)
				return;

			int count = CountGroups(this.Text, _culture);

			base.Text = DoubleToStringCurrency(TryParseCurrency(this.Text, !overridesCulture), !overridesCulture);
			
			// adujst caret position
			this.SelectionStart = cursorPos + CountGroups(this.Text, _culture) - count;
		}

		#endregion Key events

		#region Helpers
		private int CountDigits()
		{
			int sepIndex = this.Text.IndexOf(separator) + 1; //index start to 0
			return IsCurrencySymbolBefore ? this.Text.Trim().Length - sepIndex : this.Text.Trim().Length - 1 - sepIndex; 
		}
		private string DoubleToStringCurrency(double d, bool useCultureFormat)
		{
			if (useCultureFormat)
			{
				return d.ToString("C", _culture);
			}
			else
			{
				return d.ToString("C" + _digitsCount.ToString(_culture));
			}
		}

		private double TryParseCurrency(string text, bool useCultureFormat)
		{
			double d;
			if( useCultureFormat)
			{
				double.TryParse(text, System.Globalization.NumberStyles.Currency, _culture, out d);
			}
			else
			{
				NumberStyles s = NumberStyles.AllowThousands | NumberStyles.AllowTrailingWhite | NumberStyles.AllowDecimalPoint | NumberStyles.AllowCurrencySymbol;
				double.TryParse(text, s, _culture, out d);
			}
			return d;
		}

		private bool IsCurrencySymbolBefore
		{
			get
			{
				return char.IsSymbol(this.Text[0]);
			}
		}

		/// <summary>
		/// Coint number of groups in value.
		/// </summary>
		/// <param name="value"></param>
		/// <param name="format">CultureInfo containing number format</param>
		/// <returns>Groups count.</returns>
		private static int CountGroups(string value, CultureInfo format)
		{
			int count = 0;
			NumberFormatInfo nfi = format.NumberFormat;

			for(int i = 0; i < value.Length - 1 ; ++i)
				if(value[i] == nfi.NumberGroupSeparator[0])
					count++;

			return count;
		}
		#endregion Helpers

		#region Properties
		/// <summary>
		/// Gets or sets the culture associated to textbox.
		/// </summary>
		public System.Globalization.CultureInfo Culture
		{
			get { return this._culture; }
			set 
			{
				double d = TryParseCurrency(this.Text, !overridesCulture);
				
				if (value.IsNeutralCulture)
					value = CultureInfo.InvariantCulture;
				
				this._culture = value;
				
				_digitsCount = value.NumberFormat.CurrencyDecimalDigits;
				separator = _culture.NumberFormat.CurrencyDecimalSeparator;

				this.Text = DoubleToStringCurrency(d, !overridesCulture);
			}
		}

		/// <summary>
		/// Gets or sets the number of decimals after separator.
		/// </summary>
		public int DigitsCount
		{
			get { return this._digitsCount; }
			set 
			{ 
				this._digitsCount = value; 
				overridesCulture = value != this._culture.NumberFormat.CurrencyDecimalDigits;
			}
		}

		/// <summary>
		/// Ovverides Text property to format string.
		/// </summary>
		public new string Text
		{
			get
			{
				return base.Text;
			}
			set
			{
				double empty = 0;
				base.Text = value.Trim().Length > 0 ? value : empty.ToString("C", _culture);
				this.SelectionStart = Convert.ToInt32(IsCurrencySymbolBefore);
			}
		}

		/// <summary>
		/// Gets or sets the numeric value of the represented string.
		/// </summary>
		public double Value
		{
			get
			{
				return TryParseCurrency(this.Text, !overridesCulture);
			}
			set
			{
				base.Text = value.ToString();
				this.SelectionStart = IsCurrencySymbolBefore ? 1 : 0;
			}
		}
		#endregion Properties

	}
}

A voir également

Ajouter un commentaire

Commentaires

Tahiti Jon
Messages postés
2
Date d'inscription
samedi 18 août 2007
Statut
Membre
Dernière intervention
12 août 2009
-
excellent
Matt113
Messages postés
1
Date d'inscription
vendredi 10 octobre 2003
Statut
Membre
Dernière intervention
23 février 2010
-
Super pratique et marche du tonnerre.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.