I have an assembly that contains several user controls. For this user controls assembly I want to have a resource dictionary. All the user controls within the assembly should be able to access the resource dictionary. Do I have to add
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
...
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
to every user control that should utilize the resource dictionary, or is there some way of putting it in one place and just referencing it?
can I then also reference it in my main application, or does that require a MergedDictionaries call as well?
Edit: the main application is in a separate project/assembly than the user controls.
is there some way of putting it in one place and just referencing it?
Put your merged dictionaries reference to your resource dictionaries into your 'App.xaml' file and it will be accessible throughout your application, you will need no futher reference.
can I then also reference it in my main application, or does that require a MergedDictionaries call as well?
No the scope of 'App.xaml' falls over the entire application, so this should work fine (does for me :) ).
Update: How to reference resource dictionary stored items from user control.
Within your main project add a reference to your user control library. Your user controls will be accessible and you can use them in you application as desired.
The process of adding the resource dictionary reference in the App.xaml will mean that all controls can reference styles and data templates etc. defined in the resource dictionaries, so it it merely a matter of referencing them:
e.g.
Style="{StaticResource MyButtonStyle}"
This method works for both composite applications and regular WPF applications. Note that Visual Studio is no good at loading these styles from Linked XAML files (resource dictionary) but expression blend deals with it and will give the editor preview.
You can use a Pack URL to reference resource dictionaries across assemblies. For example, in Prism projects (which have multiple modules, each in its own assembly), I store my common resource dictionaries in a ResourceDictionaries folder in a project titled Common. Then I merge these dictionaries as needed into the app's modules by using markup similar to this in each module's XAML view:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Common;component/ResourceDictionaries/DemoDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
You can find further information here.
If the "App.xaml" approach doesn't work for you then you might be interessted in this discussion:
Best Practices: How to handle shared resources in a modular application?
jbe
Related
Right now in our application, which has many modules/projects in the solution, we have a specific project to hold resources called "Resource.Dictionaries", and inside that project are individual ResourceDictionary XAML files for each and every style we make.
Then, for each instance where we need one of these styles, we call it inside the resources property of the topmost parent in each view/usercontrol/data template or in c# if it's a custom control.
In short, my question is this; does putting all of our styles and other resources in the app.xaml slow anything down (even if app.xaml just becomes one big merged dictionary pointing towards our remote Resource.Dictionaries), or is it best to continue referencing the styles/other resources ONLY where and when they're needed.
I created a custom content control with its default template.
The template though is not located in the location "Themes\Generic.xaml" as it is supposed to be. Instead I placed it in a separate resource dictionary with a different name.
It is merged along with other resource dictionaries in the App.xaml resource dictionary.
Running the code yielded no errors and the control is visible. I tested the application on other machines and the code ran just fine , I would like to point out that these machines are development machines.
Testing the application on the client machines (non development) then revealed some strange behaviour. The custom control was not visible; it would only be visible on 1 out 3 client machines.
I was able to fix the problem by putting the template in "Themes\Generic.xaml".
My question is how was it able to work without having to put the template in "Themes\Generic.xaml" ? I have searched on Google but I could find any clear cut explaination .
Thank you
For your templates to be applied they need to be present in Themes\Generic.xaml.
The good news is that you may merge them here, which I find to be good practice, and makes your code cleaner. Often my generic.xaml consists of only this, one X.Generic.xaml for all your cust. controls.
Themes/Generic.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
...>
<!-- Your custom controls split into separate files -->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/YourNamespace;component/Themes/ControlA.Generic.xaml" />
<ResourceDictionary Source="/YourNamespace;component/Themes/ControlB.Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
I'm going crazy with different XAML designer errors in my PRISM application.
I have custom controls inside Infrastructure project and it seems that all referencing projects have issue loading control template at some point.
Everything runs good at runtime but VS2010 just doesn't work with all kind of errors.
I know for sure it is related to custom control not properly loading style from generic.xaml for some reason.
What I want to try is to drop generic.xaml all together and switch to use named templates for my custom controls. This way I can always merge resource files so VS know where to look for stuff.
Do you think this is viable solution?
How do I populate DefaultStyleKey from named style?
This is not a viable solution: custom controls pull their information from Themes/generic.xaml. This is baked into the runtime.
If you're building a WPF/Silverlight composite application, you'll need to put your generic.xaml in your WPF project and link it to your Silverlight project. That's the reverse of Prism guidance, but is required due to a bug with linked XAML files that are not at the root level in WPF projects.
Without generic.xaml, it is some what difficult but with help of generic.xaml you can switch to use named templates for your custom controls. just simply adding following code in generic.xaml
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/CPMS.Utility.Controls;component/Controls/MyUc/Style/DBLoginForm.xaml" />
</ResourceDictionary.MergedDictionaries>
I usually define style and control template in App.xml under tab.
So, while designing the UI, I can see the UI with the style applied in design view in Visual Studio 2008 with .NET3.5.
However, in another case, sometimes I make UserControl only project and in that case, there's no App.xml so the UI is appeared as default appearance in design view. It's hard to know actual looking in runtime.
Is there any way to apply style to UserControl, too?
If there's a way to share same style and template between application project and UserControl project, that would be perfect!
Please let me know if there's a solution.
You can keep your styles in a separate ResourceDictionary in your control project. Then you need to Merge Dictionaries in the Resources block at the top of every user control:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyControlLibraryStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
The problem with this approach is of course that you lose any benefit that App-level styles would give you (like styling differently for different applications) because now the styles are all determined by the underlying control.
I have the following:
MainApp
- Assembly 1 (Contains UserContolA)
- Assembly 2 (Contains UserControlB)
- Etc.
Not every Assembly will be loaded though, so
Neither assembly can compile if I try to assign resources to controls (button, combobox, etc.) that it can't find because I want my MainApp to dictate those resources. But, if I include the resources in the assemblies it seems that I can't override them (because WPF goes from bottom-up for resources giving prioroty to those closest to the bottom).
Also, I'm afraid even if I do solve this problem trying to get it to be dynamic in a way that a user can select from different "themes" that it'd make it even more difficult.
I included prism in the topic because I plan to use that as my framework, but haven't looked deep enough into it to see if it affects this in any way or has something built into it already, which would be a Godsave.
Really what you are asking is what is the best approach to splitting up a WPF application into multiple assemblies. Your strategy is to create reusable control libraries and let the app integrate everything. Great so far. The last issue you need to address is resources. To handle that you need to add a Themes\Generic.xaml and move all the resources in your library into it. Then the library can find all the resources it needs and the application can override it if it so wishes.
Here is a good article that discusses some of the issues related to resources across multiple assemblies:
Control Authoring Overview
Also be sure to set up your control assembly attributes so that Generic.xaml will be searched:
[assembly: ThemeInfo(
ResourceDictionaryLocation.None,
ResourceDictionaryLocation.SourceAssembly)]
Edit:
The above solution applies to custom controls, not to UserControl resources. To handle UserControl resources in a separate assembly that the main application can override, you can use this approach:
Use {DynamicResource ...} and simply leave the resource definition out of the UserControl.
The problem with this is that although the resource will be located correctly at run-time, it won't be found during design-time and this can make your UserControl very hard to work with. There are two workarounds for this problem:
Use Expression Blend together with its "Design Time Resources" feature. Simply opening a project that has resources that cannot be resolved will cause Blend to prompt you for which resources to use at design-time.
Use Visual Studio to design your UserControl and include design time resources in the XAML itself.
For Visual Studio you can include this in your UserControl while designing it only:
<UserControl.Resources>
<ResourceDictionary Source="/YourControlLibrary;component/DesignTimeResources.xaml"/>
</UserControl.Resources>
Once you are done designing it, simply comment out that code in the XAML. It's inconvenient, but until Visual Studio supports design time resources, at least it works.