How to make RDLC use date format from control panel

Viewed 352

I have some RDLC reports being generated by my app which include a date field. I want to display this date field using the user's preferred settings from the Region & Language control panel (which you would think would be the default behaviour, but apparently not).

The report textbox is formatted as a date using one of the locale-specific formats -- in the properties it appears as format D.

The Thread.CurrentThread.CurrentCulture has not been changed by my app. When I run DateTime.Now.ToString("D") in my own code (either before or after displaying a report) it behaves as I expect when I change the control panel settings:

  • set to "English (NZ)" and the default long date format, I get Friday, 16 October 2020.
  • set to "English (NZ)" and the alternate long date format, I get 16 October 2020.
  • set to "French (France)" and the default long date format, I get vendredi 16 octobre 2020.
  • set to "French (France)" and the alternate long date format, I get 16 octobre 2020.

When I view a report, however, it always displays in English (regardless of the region selected), although I do get either the default or alternate formats as expected.

Reading up on that, I discovered that apparently the default behaviour is incorrect and you have to explicitly set the report language to =User!Language to make it obey the language settings (and this was claimed to make it use the CurrentCulture) -- but after doing that, it now correctly follows the language but only ever uses the default format, never the alternate format, regardless of the control panel setting. This is an improvement, but still not correct.

How do I get the report viewer to behave like regular .NET ToString() instead, and actually use the current culture? I do not want to hard-code any particular language or format in the report.

I am currently using Microsoft.ReportingServices.ReportViewerControl.Winforms.150.1404.0.nupkg.

1 Answers

Ok, this is a little bit evil, but I don't see any alternative until Microsoft fix their bug.

  1. Ensure that reports do not set the Language to =User!Language (and don't set the Language at all unless you want to force particular non-defaults for that particular report).
  2. Add the Lib.Harmony NuGet package to your project. (The code below assumes you're using 1.2; you might need to tweak it slightly for a later version.)
  3. Add the following class:
    public static class ReportViewerBugFix
    {
        public static void Patch()
        {
            HarmonyInstance.Create("fix.broken.microsoft.reportviewer").Patch(
                AccessTools.Method("Microsoft.ReportingServices.Diagnostics.Localization,Microsoft.ReportViewer.Common:get_DefaultReportServerSpecificCulture"),
                prefix: new HarmonyMethod(AccessTools.Method(typeof(ReportViewerBugFix), nameof(PatchDefaultReportServerSpecificCulture))));
        }

        private static bool PatchDefaultReportServerSpecificCulture(ref CultureInfo __result)
        {
            __result = CultureInfo.CurrentCulture;
            return false;
        }
    }
  1. Call ReportViewerBugFix.Patch() early in your app startup.

(For extra paranoia, you could capture CultureInfo.CurrentCulture at the time that Patch is called and return that value instead of re-querying it later. However the above worked as-is for all the cases that I tried.)

This changes the return value of DefaultReportServerSpecificCulture to be the same as ClientPrimaryCulture, because that's easier to do in an external patch than to make EvaluateReportLanguage call the right thing instead (which would probably be the better solution, with access to the code). But it's ok because there's absolutely no reason you'd ever want to use the Windows UI Language in the first place.

Related