WPF merged resource dictionaries in every user control - bad idea? - wpf

I keep my app's resources in a separate DLL and reference them in my main EXE using something like this in App.xaml:-
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MyThemesAssembly;component/Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
When I edit a window that's in the main EXE project, the VS2010 designer doesn't recognise any resources from the other assembly, so I don't see any styling applied (not really an issue as I always work in the XAML view). However Resharper doesn't recognise these external resource names either, resulting in lots of squiggles under resource names when I'm editing XAML.
I've found that I can fix both the VS designer and Resharper by including the above XAML in each window and user control, but is this going to have an adverse effect on memory and/or performance? Will each window get a separate copy of the resources?

We had a problem in our application with the use of ResourceDictionaries referenced in each UserControl / View. I advise against that. We managed to reduce our application's memory footprint by like 300 mb by the use of SharedResourceDictionaries. I looks like you will end up with the ResourceDictionary being instantiated once for every single UserControl in your application. Don't do that just to fix VS designer.

Try using VS2012.
I have a test project which I was using which I was doing resource dictionary merging from an external assembly and in my app.xaml I have this:
<Application x:Class="WpfPackDictionaries.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WPFCommonLibrary;component/Vectors/Vectors.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Then in my mainwindow.xaml I have this where the path pulls in a style ModifiablePathStyle:
<Window xmlns:Control="clr-namespace:WPF.Common.Control;assembly=WPFCommonLibrary" x:Class="WpfPackDictionaries.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Path Style="{StaticResource ModifiablePathStyle}" Fill="Red"/>
<Control:Jabberwocky />
</Grid>
</Window>
Intellisense/Resharper (V7.1 10/31 (Early Access Build)) recognizes the style and I have no squigglies:
Hence have you tried to work in VS2012?

VS2012 is able to 'see' resources since VS XAML designer loads and executes your code in design-time, so VS can inspect what resources will be available at runtime. ReSharper never uses design-time code execution (since this requires your code always be in compilable state) so XAML support became a bit more complex task.
ReSharper 8.0 implemented support for BAML decompilation and do extracts the list of XAML files and resolves XAML resources from referenced binary assemblies.

Related

Modern UI (WPF): Trying to use MUI for a WPF control in class library

I'm trying to use MUI framework for a existing WPF control (the WPF control is in class library). I've looked the MUI example for a modern window and tried to copy the resourceDictionary I found in the App.xaml.
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.xaml" />
<ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.Light.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
The issue that at design time, the UI seems to be have changed (look at the data)
but during running time, I'm getting exception (xamlparse exeption) that has an inner exception saying it was unable to locate the file or assembly FirstFloor.ModernUI.
I've used nuget to include the MUI framework the dll's copy to local is true.
I've also tried
<ResourceDictionary Source="pack://application:,,,/FirstFloor.ModernUI;component/Assets/ModernUI.xaml" />
<ResourceDictionary Source="pack://application:,,,/FirstFloor.ModernUI;component/Assets/ModernUI.Light.xaml"/>
and it doesn't work.
Any help would appreciated!
pack://application: apparently scope to the calling application. In my case the compiled dll was called from an exectuable (3rd party vendor SOLIDWORKS). I had to copy paste the FirstFloor.ModernUI dll in the folder of the SOLIDWORKS executable that solves the problem.
If anyone can provide a better answer (that doesn't involve this manually intervention), I'll tick their answer.

Styling project in visual studio solution (WPF XAML)?

Regarding this question and Marc's answer, I find this solution perfect, but I have trouble organizing my solution to make it functional.
How can I create a styling project that contains only XAML and reference to sub XAML, and how can I use it elsewhere in my solution? What is the visual studio project used by Marc in his answer to create the styling project?
Thank you,
B
You could create a WPF User Control Library in Visual Studio and add ResourceDictionary items where you define your XAML resources to it.
You then add a reference to this WPF User Control Library from your WPF Application project (Project->Add Reference in Visual Studio) and merge the resource dictionaries that are defined in the library in the App.xaml of your application:
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication4"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WpfUserControlLibrary1;component/Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Replace "WpfUserControlLibrary1" with the name of the WPF User Control Library and "Dictionary1" with the name of the ResourceDictionary that you added to this project.

Shared WPF resources inside an activity designer library

I'm developing a bunch of custom activity designers, which contain custom controls, images, styles etc. The designer XAMLs are spread over several subdirectories in a library project (not a WPF application, therefore no app.xaml available)
I need a central place to store resources, just like the app.xaml in a regular WPF application.
Currently I use a projectdir\Properties\lib.xaml file like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTemplate x:Key="TrafficLight">
...
</ControlTemplate>
</ResourceDictionary>
And reference this from all my designer XAMLs like this:
<sap:ActivityDesigner.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/ActDesLib;component/Properties/lib.xaml" />
</ResourceDictionary.MergedDictionaries>
where ActDesLib is the name of my assembly.
This does work, but it looks a bit clumsy. Is there a better way to do it?
Is there some "magic" app.xaml-like file that gets included automatically for a library project, without the need to add any special markup to the individual XAML files? That would make it so much easier to enforce a consistent style, even with multiple developers working on the different designers.
BTW: I tried to use relative pathes in the Source="..." attribute. This did not work when using my activities in a workflow inside VS2010, it could not find the resources then. With the absolute path, containing assembly name, it works fine. But is there no way that VS2010 or a rehosted designer can find out the path to the resource dictionary file automatically, with only relative references inside my XAMLs?

WPF - using styles/resources from another assembly

I'm new to WPF and struggling to use styles that live in a separate assembly. This is what I'm doing:-
I have a class library project with a \Themes folder containing a "generic.xaml" that merges a number of xaml files from a subfolder within \Themes:-
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Metro\CoreStyles.xaml" />
... etc ...
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
My solution also has a WPF application project, and in here the App.xaml merges in the resources from my library project like so:-
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MyThemeLibrary;component/Themes/generic.xaml"/>
... etc...
Standard stuff so far.
Finally, I have a third project - a WPF user control library. These controls use these common styles, typically with "Style={StaticResource SomeStyle}". I can run the app and it all looks fine, but the problem is I don't get design-time support when writing the user controls - the design surface is basically empty.
Another SO article suggested adding an App.xaml to the user control library project, and merging in the resources as above. This works and I get my design-time support, however I get an error when trying to build the solution:
Library project file cannot specify ApplicationDefinition element.
I have tried changing the App.xaml build action from "ApplicationDefinition" to "Page", as has been suggested elsewhere. This gets the build working but I lose the design-time support as the user controls can no longer see the styles.
Is there a way around this problem, or failing this, an alternative way of using styles from another assembly?
Thanks in advance
Andrew
The error message says it. You cannot use "pack://application..." syntax in a library project. You should do this in your wpf project.

sharing WPF ControlTemplates

I'm trying to learn more about WPF. I ran through an online tutorial that created a button and then created a template to be applied to additional buttons. The problem is this template is in the Window.xaml and I can only access the template from within that application. How do I make the template more globablly available? I'm thinking of some way to reference the xaml like you can reference an assembly from a different project or solution.
You can use "resource dictionaries" which you reference in your App.xaml like this (Expression Blend does it automatically):
<Application.Resources>
<!-- Resources scoped at the Application level should be defined here. -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ResourceDictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
How to reference a resource from another assembly, use pack URI syntax. This link covers it as well.

Resources