Reputation: 1205
I've often been troubled by designer issues where the XAML designer (WPF's "xdesproc") will display my controls in one way, but they will be displayed in a totally different way at run time. Often these differences come down to the fact that the static resources used at runtime (at the application level) are not the ones used in the designer.
This happens primarily when a large solution is made up of a number of projects - most of which are user control libraries, and a few of them are startup projects (applications, test harnesses, etc).
While using VS to edit a usercontrol in one of the libraries, I've discovered a trick from Blend whereby you can introduce the "DesignTimeResources.xaml" file in a project and visual studio will "respect" it and merge these resources as a supplement to the ones in the user control itself (as if they had been found in the logical tree for that usercontrol).
I thought that this trick would be sufficient so that I would be able to forgo the need for application-level resources in the designer. However, the "DesignTimeResources.xaml" doesn't solve all my problems. Nor does xdesproc consider this as a sufficient source of application-level resources either (ie. xdesproc might consider loading this both as its application-level resources and in the logical tree of the user control if it wanted to.)
After snooping on xdesproc with procmon, I find it behaves in very unusual ways in order to find the stuff that it wants to use for its application-level resources. The search mechanism that it uses does not seem very well-defined. If one is not careful, it either neglects to establish any application-level resources at all, or it picks randomly from one of the projects it might find in the outer solution (a project which is possibly not relevant to the usercontrol library in any way, but is found and is used because it contains a project item which happens to be an "Application/").
Can someone tell me if there is supposed to be a well-defined way that the xdesproc finds application-level resources while editing a usercontrol? My work-around is a lot of obsessive tinkering that involves unloading projects. I temporary unload all projects from my solution that have "Application" elements, with the exception of one. Unless I do this, xdesproc is liable to randomly pick one of them out and start happily using it for its app-level resources. It doesn't seem to limit itself to the current startup project in the VS IDE.
I would appreciate any pointers to help me understand what xdesproc thinks it should be using for its app resources. I suspect it was programmed to be "smart" and "just work". And it probably does work in many cases, except when it doesn't.
Upvotes: 3
Views: 2815
Reputation: 665
To fix this type of issue, I have not made use of "DesignTimeResources.xaml" (I didn't know that was a thing).
When I have assemblies with controls that I would like to use the designer for, I make the App.xaml (and App.xaml.cs) in the root (eg. copy from a startup-assembly). I have the BuildAction set to "Page".
In the App.xaml I reference the resource(s) which are expected to be loaded when the assembly is used.
We have som daisy-chained assemblies, so each assembly with controls has a "AllDictionaries.xaml" resource dictionary, that can be referenced by the assemblies, which use it.
Example of App.xaml content:
<Application x:Class="RD.Controls.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/RD.Controls;component/AllDictionaries.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Having the App.xaml file in the assembly ensures the 'main dictionary' is loaded, which references any other needed resources from references assemblies.
Upvotes: 1
Reputation: 1205
I have a bit more of an answer on this topic (from someone other than myself). This is from a Microsoft engineer in the visual studio developer community...
see link:
I took a quick look at our logic for finding the application document. Your description on StackOverflow seems accurate. I'd summarize the designer's preference order as:
1.Application document from the project containing the open XAML file.
2.Application document from the startup project
3.Application document from the first project we find that references the project containing the open XAML file.
There is no designer feature to tell users which application document we chose. We generally assume that #1 or #2 will be used and that that's what most users want. I can understand that hitting #3 would lead to unpredictable results in complex solutions.
Upvotes: 1
Reputation: 1205
Here is what I found after much trial-and-error. As you are editing a user control in a library, the designer will scan the entire solution and will attempt to find application-level resources for you based on a number of complex criteria. The search is not quite as random as I first believed. It will only find and use resources if they are:
Given how far and wide the designer searches for something to use for its application-level resources, there are some unfortunate consequences that affect a developer in a practical way:
To overcome these practical issues, I typically end up unloading all project candidates that would otherwise be found by the designer. This forces the designer to rely on the local "DesignTimeResources.xaml" in the usercontrol library itself. Alternatively you can unload all except a single project that is currently used as the startup ... but just make sure to review its resources and they are acceptable for use at runtime and for use by the designer as you edit your controls.
It seems a bit scary to me how the WPF designer ("xdesproc") goes hunting across the entire solution in a haphazard and poorly defined way. I suspect I'm not the only one that has been "bitten" by WPF designer issues related to my application resources. I've never found very much on the Internet about how the designer is supposed to discover application-level resources. Perhaps things are intentionally ambiguous so that the behavior can be changed over time. Although I noticed that someone did recently report a VS 2017 bug related to "DesignTimeResources.xaml", so at least that's not something that is uncommon anymore.
Hopefully this information will be helpful if/when you run into designer problems that are difficult to explain. Please comment if you observe a different behavior than I did while experimenting with VS 2017.
Upvotes: 4