2023-06-12

The Trouble with XAML Hot Reload in WPF

The XAML Hot Reload feature of WPF is extremely useful because GUI work often involves tweaking visual aspects of an application, so being able to modify XAML, save it, and immediately see the changes on the screen saves a huge amount of time as opposed to having to terminate the application, modify the code, re-compile, re-run, and go clickety-clickety-click to navigate to the same page and finally see your changes.

Unfortunately, as a WPF project grows, the XAML Hot Reload feature inevitably one day stops working: You modify your XAML, you save the XAML file, and yet nothing changes on the screen. The message "No changes were found" appears in the Hot Reload tab of the Visual Studio Output Window, but it is a damned lie, because you just made changes. This can really be a problem.

When you find yourself in this extremely unpleasant situation, here is a list of things to try:

  1. First of all, the usual:
    • Exit Visual Studio and re-launch Visual Studio.
  2. Then, the all too familiar:
    • Exit Visual Studio, delete the `.vs` directory in your solution, and re-launch Visual Studio.
    • Exit Visual Studio, delete the `.vs` directory, clean all output directories, and re-launch Visual Studio.
      • No, you cannot just go to the Build menu and select "Clean Solution"; that would make too much sense. The "Clean Solution" option is a joke that never fixes anything; instead, you have to have a script that actually visits every bin and obj directory and deletes its contents, and you also have to make sure that Visual Studio is not running when you run this script.
  3. And then, the arcane:
    • Make sure all your dependency properties are done properly. What constitutes "properly" for Microsoft is actually quite counter-intuitive and quite preposterous: every dependency property must - A: be backed by a field of type `System.Windows.DependencyProperty` which must - B: be `public static`, and whose name must - C: start with the name of the corresponding C# property, and must - D: end with the suffix `Property`. All this magic must be done exactly right every single time, or else all sorts of other magic do not work anymore, for example the XAML Hot Reload magic.
    • If you have any styles where you had to specify the type of the data context so as to enjoy type safety and auto-completion when editing, (and to avoid ReSharper warings,) make sure that you do not use the `d:DataContext="{d:DesignInstance ...` magical incantation suggested by some folks out there. If something like this appears outside of the root XAML element, XAML Hot Reload will stop working. Instead, use the following magical incantation:
      <Style TargetType="{x:Type ...}">
          <d:Style.DataContext>
              <x:Type Type="SomeViewModel" />
          </d:Style.DataContext>

Ultimately, all problems with XAML Hot Reload can be traced down to the fact that it embraces silent failure. In my experience any feature that involves silent failure is a failure as a whole, because:

As a rule, anything that can break will at some point break; if it gives you some hint as to why it broke, or even just a hint that it just now broke, then you can fix it; but if it gives no hint, then you can't fix it.

No comments:

Post a Comment