четверг, 25 декабря 2014 г.

WPF set application-wide Culture, NumberFormat, Decimal separator

WPF by default uses built-in culture settings that come with .Net Framework libraries.

For example, for ru-RU culture double must look like 123456,789, for en-US like 123456.789, so if you don't want your users to be angry, you must set your application culture at startup. However, our users want to see doubles like in en-US culture, e.g. 123456.789

There are two ways to do this:

1. Modify current culture settings. And that is awful
   a. Not all controls support such behaviour
   b. This code breaks all your hopes:
    XmlLanguage xmlLanguage = XmlLanguage.GetLanguage("ru-RU");
    FrameworkElement.LanguageProperty.OverrideMetadata(typeof (FrameworkElement),
                                                       new FrameworkPropertyMetadata(xmlLanguage)); 

    XmlLanguage ignore all modifications to Thread.CurrentThread.CurrentCulture

2. Register your own culture (works if your users can get administator rights).

        private const string CultureName = "ru-MIT";
        private const string cultureEnglishName = "ru-MIT";
        private const string cultureNativeName = "Русский (Мит)";

        private static void Main(string[] args)

        private static void CreateAndRegisterOwnCulture()
            var ownCulture = new CultureAndRegionInfoBuilder(CultureName, CultureAndRegionModifiers.None);

            var parentCulture = new CultureInfo("ru-RU");
            var region = new RegionInfo("RU");

            ownCulture.CultureEnglishName = cultureEnglishName;
            ownCulture.CultureNativeName = cultureNativeName;

            var nfi = (NumberFormatInfo) parentCulture.NumberFormat.Clone();
            nfi.NumberDecimalSeparator = ".";
            nfi.NumberGroupSeparator = " ";
            nfi.CurrencyDecimalSeparator = ".";
            nfi.CurrencyGroupSeparator = " ";

            ownCulture.NumberFormat = nfi;
            ownCulture.Parent = parentCulture;

            if (SystemHasMitCulture())
                Console.WriteLine(">>> System already has own culture :)");

            // Admin rights are needed here
            // CultureAndRegionInfoBuilder.Unregister(CultureName);

                // Admin rights are needed here
                Console.WriteLine(">>> Trying to set own culture");
                Console.WriteLine(">>> Own culture set successfully");
            catch (UnauthorizedAccessException)
                Console.WriteLine(">>> Set own culture failed :(");
            catch (InvalidOperationException)
                Console.WriteLine(">>> Culture is already registered :)");

        private static bool SystemHasMitCulture()
            return CultureInfo.GetCultures(CultureTypes.UserCustomCulture).Any(ci => (ci.Name == CultureName));

The same code on Github Gist: https://gist.github.com/Snegovikufa/f051959dd105b7e56405

Python setup.py build vcvarsall.bat error

If you get this error when running python setup.py build

error: Unable to find vcvarsall.bat

You need:
1. Install Microsoft Visual C++ Compiler for Python 2.7
2. Upgrade setuptools
3. Try again

Configuring Jenkins for C# projects

Steps in my build configuration Restore nuget packages chcp 1251 .nuget\nuget.exe restore Swag.sln Build solution chcp 1251 cmd.e...