SuperPeanut SuperPeanut - 7 months ago 137
Vb.net Question

Regional Settings Override in .NET Framework

I am currently stuck with a Number formatting issue and I really don't know how to solve it.

I use a function from the

Support
assembly :

'StringToFormat looks like "123.456789"
'FormatInfo looks like "0.000" (must display three decimals)
Support.Format(StringToFormat, FormatInfo)


It works fine exept that when my regional settings are not set properly, it doesn't work...
StringToFormat
is a variable that come from another application (over TCP/IP) and I can't change it. So when the Decimal Separator is set to coma instead of a dot, the Format function is doing weird stuff and not displaying my values correctly.

To solve this, I wrote a small function that actually creates a new culture and makes sure that the decimal separator is the dot :

Sub UpdateRegionalSettings()
'I call this everytime I start my application
My.Application.ChangeCulture("x-en-US-custom")
End Sub

Sub CreateMyCulture()
'This function is called only if the culture doesn't exist yet
Dim C As New CultureAndRegionInfoBuilder("x-en-US-custom", CultureAndRegionModifiers.None)
C.LoadDataFromCultureInfo(New CultureInfo("en-US"))
C.LoadDataFromRegionInfo(New RegionInfo("US"))
C.NumberFormat.NumberDecimalSeparator = "."
C.NumberFormat.CurrencyDecimalSeparator = "."
C.Register()
End Sub


However, this doesn't seem to work as when I go to regional settings and change the separator to a coma the Format function is going weird again. It is like these parameters override anything I can say in my program...

My question is : How can I force the
Support.Format
(and others) function to use the dot as a decimal separator without having to manually set it into region and language of the control panel ?

Answer

Here is one method to change the culture for the app at runtime only. In form load all cultures are loaded so you can tinker with them and see results in text box controls for double and date time.

Imports System.Globalization
''' <summary>
''' Requires 
'''    1 ComboBox: cboCultures
'''    2 TextBoxes: TextBox1, TextBox2
'''    1 DateTimePicker: DateTimePicker1
''' </summary>
Public Class Form1
    ' Used to set cboCultures selected item and for restoring the current culture
    Private OriginalCultureName As String = ""
    Private OriginalCultureIndex As Integer = 0
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        OriginalCultureName = Application.CurrentCulture.Name
        DateTimePicker1.Format = DateTimePickerFormat.Custom

        cboCultures.DisplayMember = "DisplayName"
        cboCultures.ValueMember = "Code"
        cboCultures.DropDownStyle = ComboBoxStyle.DropDownList

        Dim CultureList =
            (
                From cultureitem In CultureInfo.GetCultures(CultureTypes.SpecificCultures)
                Order By cultureitem.EnglishName
                Select New With
                       {
                           .DisplayName = cultureitem.EnglishName,
                           .Code = cultureitem.Name
                       }
            ).ToList

        cboCultures.DataSource = CultureList

        ' get current culture so we can select it in cboCultures
        Dim item =
            (
                From T In CultureList _
                .Select(
                    Function(cultureitem, indexer)
                        Return New With {.Index = indexer, .Name = cultureitem.Code}
                    End Function)
                Where T.Name = OriginalCultureName
            ).First

        OriginalCultureIndex = item.Index
        cboCultures.SelectedIndex = OriginalCultureIndex
    End Sub

    Private Sub cmdChange_Click(sender As Object, e As EventArgs) Handles cmdChange.Click
        Application.CurrentCulture = New CultureInfo(cboCultures.SelectedValue.ToString)
        Demo()
    End Sub
    ''' <summary>
    ''' Show results for date and double
    ''' </summary>
    Private Sub Demo()
        DateTimePicker1.CustomFormat = DateTimeFormatInfo.CurrentInfo.FullDateTimePattern
        TextBox1.Text = DateTimePicker1.Value.ToString
        Dim value As Double = 123.456789
        TextBox2.Text = value.ToString
    End Sub
    Private Sub cmdRestore_Click(sender As Object, e As EventArgs) Handles cmdRestore.Click
        Application.CurrentCulture = New CultureInfo(OriginalCultureName)
        cboCultures.SelectedIndex = OriginalCultureIndex
        cmdChange.PerformClick()
        Demo()
    End Sub
End Class

Update: I used string formatting as per below and it worked for me

Private Sub Demo()
    DateTimePicker1.CustomFormat = DateTimeFormatInfo.CurrentInfo.FullDateTimePattern
    TextBox1.Text = DateTimePicker1.Value.ToString
    Dim value As Double = 123.456789
    TextBox2.Text = value.ToString("c2")
    TextBox3.Text = String.Format("{0:c2}", value)
End Sub

enter image description here

enter image description here

Comments