Ticket T404423
Visible to All Users

ASPxTextBox - How to dynamically change the currency mask based on the selected culture

created 9 years ago

[DevExpress Support Team: CLONED FROM T352836: Custom Decimal Property Editor not invoked when Currency value is changed]

How to set the AspxTextBox editors mask property based on a culture. I tried as below,

C#
DecimalPropertyEditor.MaskSettings.Mask = String.Format("{0}<0..99999g>.<{1}..{2}>", CurrentCulture.NumberFormat.CurrencySymbol, new String('0', CurrentCulture.NumberFormat.CurrencyDecimalDigits), new String('9', CurrentCulture.NumberFormat.CurrencyDecimalDigits));

But it uses only DecimalDigits and Currency Symbol and thus incomplete. I would like to mask the input entirely based on the selected culture(Culture can be selected from the drop down) as I did in the Winforms solution using the below code, so that the windows solution and win solution is in synch

C#
DecimalProperty.Mask.Culture = CultureInfo.GetCultureInfo(Currency.Culture.CultureID); //To format the currency and numeric fields based on the number format designed for the culture chosen DecimalProperty.DisplayFormat.Format = DecimalProperty.Mask.Culture.NumberFormat;

Is it possible?

Thanks

Show previous comments (2)
KD KD
Kanagu Duraiswamy 9 years ago
    KD KD
    Kanagu Duraiswamy 9 years ago

      And the solution

      DevExpress Support Team 9 years ago

        Hello Kanagu,

        Thank you for the sample project and video file. I am working on this issue and need additional time to complete the research. I will notify you once I get results. I appreciate your patience.

        Answers approved by DevExpress Support

        created 9 years ago (modified 9 years ago)

        Hello Kanagu,

        We thoroughly researched the problematic behavior. There are two issues in the project that prevent it from proper operation.

        1. The Decimal.Parse method always throws an error. It is required to use the Decimal.Parse Method (String, NumberStyles, IFormatProvider) overload of the method because of the currency settings.
        2. Mask settings are not initialized with the required culture settings. The mask with <0…9999g> doesn't work  properly, because it automatically gets the group separator from the culture settings of the page (see the Mask Types documentation article).Since our ASP.NET editors don't provide the capability to set a mask based on CultureInfo at the moment, it is not possible to adjust the mask to work with culture settings different from the current page culture. We completely understand the importance of this behavior, especially in XAF projects, where desktop and web behavior should be similar. So we will take this case into account when planning future improvements of our editors.

        For now,  the only possible solution is to build a mask manually using the required culture's separators. I suggest  that you use the following mask:

        C#
        DecimalPropertyEditor.MaskSettings.Mask = String.Format("{0}<99{4}999>{3}<{1}..{2}>", CurrentCulture.NumberFormat.CurrencySymbol, new String('0', CurrentCulture.NumberFormat.CurrencyDecimalDigits), new String('9', CurrentCulture.NumberFormat.CurrencyDecimalDigits), CurrentCulture.NumberFormat.CurrencyDecimalSeparator,CurrentCulture.NumberFormat.CurrencyGroupSeparator);

        While it does not follow the WinForms editors' behavior completely, it should operate fine.
        In addition, it is necessary to slightly adjust the value parsing logic and remove the whitespace characters from the mask:

        C#
        if(CurrentCulture != null) { var emptyMask = String.Format("{0} {3} {2}{1}", CurrentCulture.NumberFormat.CurrencySymbol, new String('0', CurrentCulture.NumberFormat.CurrencyDecimalDigits), CurrentCulture.NumberFormat.CurrencyDecimalSeparator, CurrentCulture.NumberFormat.CurrencyGroupSeparator); if(InputString == emptyMask) InputString = string.Format("0{0}00", CurrentCulture.NumberFormat.CurrencyDecimalSeparator); InputString = InputString.Replace(" ", ""); decimalValue = Decimal.Parse(InputString, NumberStyles.Currency, CurrentCulture.NumberFormat); }

        Also, remove the following lines:

        C#
        ((ASPxTextBox)Editor).Text= ((decimal)PropertyValue).ToString("C", CurrentCulture); ... ((ASPxTextBox)InplaceViewModeEditor).Text = ((decimal)DecimalPropertyEditor.Value).ToString("C", CurrentCulture);

        I've implemented these changes in your project and attached it for your reference with a video illustrating the result. If you have further questions, feel free to contact us.

        Updated:

        It is not possible to use the ToString method in your case. To resolve the issue, I suggest you perform the following steps:

        1. Change a mask to the following one to prevent changing separators and the currency symbol to incorrect:
        C#
        DecimalPropertyEditor.MaskSettings.Mask = String.Format("\\{0}<99\\{4}999>\\{3}<{1}..{2}>", CurrentCulture.NumberFormat.CurrencySymbol,   new String('0', CurrentCulture.NumberFormat.CurrencyDecimalDigits), new String('9', CurrentCulture.NumberFormat.CurrencyDecimalDigits),   CurrentCulture.NumberFormat.CurrencyDecimalSeparator, CurrentCulture.NumberFormat.CurrencyGroupSeparator);
        1. Change the GetControlValueCore as it is shown to prevent mask reading errors:
        C#
        protected override object GetControlValueCore() { decimal decimalValue = 0; string InputString = ((ASPxTextBox)Editor).Value as string; if(CurrentCulture != null) { var emptyMask = String.Format("{0} {3} {2}{1}", CurrentCulture.NumberFormat.CurrencySymbol,   new String('0', CurrentCulture.NumberFormat.CurrencyDecimalDigits), CurrentCulture.NumberFormat.CurrencyDecimalSeparator,   CurrentCulture.NumberFormat.CurrencyGroupSeparator); if(InputString == emptyMask) InputString = string.Format("0{0}00", CurrentCulture.NumberFormat.CurrencyDecimalSeparator); InputString = InputString.Replace(" ", ""); if(InputString.Replace(CurrentCulture.NumberFormat.CurrencySymbol, "").IndexOf(CurrentCulture.NumberFormat.CurrencyGroupSeparator) == 0) InputString = CurrentCulture.NumberFormat.CurrencySymbol + InputString.Replace(CurrentCulture.NumberFormat.CurrencySymbol, "")   .Replace(CurrentCulture.NumberFormat.CurrencyGroupSeparator, "");   decimalValue = Decimal.Parse(InputString, NumberStyles.Currency, CurrentCulture.NumberFormat); } return decimalValue; }
        1. Call the SetValueToEditor method from the ReadViewModeValueCore  and ReadEditModeValueCore methods to force the editor to show a correct value:
        C#
        void SetValueToEditor(ASPxTextBox txt) { txt.Value = string.Format("{0:0.00}", PropertyValue);   if(CurrentCulture != null) { txt.Text = string.Format("{0:0.00}", PropertyValue); var maskLength = 8; var length = maskLength - txt.Text.Length; txt.Value = new string('_', length) + txt.Value; } }
          Show previous comments (8)
          DevExpress Support Team 9 years ago

            It is not possible to use the ToString method in your case. To resolve the issue, I suggest you perform the following steps:

            1. Change a mask to the following one to prevent changing separators and the currency symbol to incorrect:
            C#
            DecimalPropertyEditor.MaskSettings.Mask = String.Format("\\{0}<99\\{4}999>\\{3}<{1}..{2}>", CurrentCulture.NumberFormat.CurrencySymbol,   new String('0', CurrentCulture.NumberFormat.CurrencyDecimalDigits), new String('9', CurrentCulture.NumberFormat.CurrencyDecimalDigits),   CurrentCulture.NumberFormat.CurrencyDecimalSeparator, CurrentCulture.NumberFormat.CurrencyGroupSeparator);
            1. Change the GetControlValueCore as it is shown to prevent mask reading errors:
            C#
            protected override object GetControlValueCore() { decimal decimalValue = 0; string InputString = ((ASPxTextBox)Editor).Value as string; if(CurrentCulture != null) { var emptyMask = String.Format("{0} {3} {2}{1}", CurrentCulture.NumberFormat.CurrencySymbol,   new String('0', CurrentCulture.NumberFormat.CurrencyDecimalDigits), CurrentCulture.NumberFormat.CurrencyDecimalSeparator,   CurrentCulture.NumberFormat.CurrencyGroupSeparator); if(InputString == emptyMask) InputString = string.Format("0{0}00", CurrentCulture.NumberFormat.CurrencyDecimalSeparator); InputString = InputString.Replace(" ", ""); if(InputString.Replace(CurrentCulture.NumberFormat.CurrencySymbol, "").IndexOf(CurrentCulture.NumberFormat.CurrencyGroupSeparator) == 0) InputString = CurrentCulture.NumberFormat.CurrencySymbol + InputString.Replace(CurrentCulture.NumberFormat.CurrencySymbol, "")   .Replace(CurrentCulture.NumberFormat.CurrencyGroupSeparator, "");   decimalValue = Decimal.Parse(InputString, NumberStyles.Currency, CurrentCulture.NumberFormat); } return decimalValue; }
            1. Call the SetValueToEditor method from the ReadViewModeValueCore  and ReadEditModeValueCore methods to force the editor to show a correct value:
            C#
            void SetValueToEditor(ASPxTextBox txt) { txt.Value = string.Format("{0:0.00}", PropertyValue);   if(CurrentCulture != null) { txt.Text = string.Format("{0:0.00}", PropertyValue); var maskLength = 8; var length = maskLength - txt.Text.Length; txt.Value = new string('_', length) + txt.Value; } }

            I've modified your project and recorded a video. Don't hesitate to contact us if you have further questions.

            KD KD
            Kanagu Duraiswamy 9 years ago

              Thanks for your assistance so far, Lex.

              I found that ImmediatePostData is not working when this property editor is used. So I called WriteValue method in TextChangedEvent. And TextChangedEvent was  fired only after setting AutoPostBack to true. After these changes, every time i change the amount, i get a dialogue 'Leave/Stay' when the page is being refreshed. Is there a way for avoiding this dialogue? Or the changes that I have done is it correct to achieve immediatePostData working?

              C#
              protected override WebControl CreateEditModeControlCore() { DecimalPropertyEditor = new ASPxTextBox(); DecimalPropertyEditor.AutoPostBack = true; DecimalPropertyEditor.ID = "CustomDecimalPropertyEditorWeb"; DecimalPropertyEditor.ValueChanged += DecimalProperty_ValueChanged; DecimalPropertyEditor.TextChanged += DecimalPropertyEditor_TextChanged; void DecimalPropertyEditor_TextChanged(object sender, EventArgs e) { EditValueChangedHandler(sender, e); WriteValue(); }

              Thanks.

              DevExpress Support Team 9 years ago

                Hello Kanagu,

                To discuss your second question, I've created a separate ticket on your behalf (T409930: How to support the ImmediatePostData attribute in a custom PropertyEditor). I will reply in that ticket shortly.

                Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

                Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.