In WPF, How to apply style to UserControl in design view? - c#

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.

Related

C# WPF VS2017 - Forcing Aero theme

I'm trying to fix a rendering issue with a WPF app (a screensaver) that I wrote using VS2015 on Windows 7.
On Windows 10, the config window looks totally different and, more importantly, it's almost useless because of how it renders in Windows 10.
Here are some screenshots. First, windows 7
And Windows 10
While there are lots of little differences, and I expect that, what's unforgivable is the coloring and cut off controls. Check boxes are checked and you can't tell. Radio buttons are selected and you can't tell. You can't even see the bottom control. It's garbage.
I did some research and found that I could override the theme, forcing the use of Aero. I don't know if that will fix my problem and I'm having trouble making it work.
According to my research, if I add the following to App.xaml, it may fix things.
<Application.Resources>
<ResourceDictionary Source="/PresentationFramework.Aero;component/themes/Aero.NormalColor.xaml" />
<ResourceDictionary Source="pack://application:,,,/WPFToolkit;component/Themes/Aero.NormalColor.xaml" />
</Application.Resources>
But, doing that gives me a warning in VS2017:
The property "Resources" can only be set once.
So, I can't even test it. I have yet to find a way around this. How do I make it work?
---------- UPDATE 1 ----------
With help from comments I got to:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/PresentationFramework.Aero;component/themes/Aero.NormalColor.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
However, now the app will not run at all.
Your app has entered a break state, but there is no code to show because all threads were executing external code (typically system or framework code).
Original source on GitHub
You are hard coding the size of the Config window.
Height="358" Width="300"
That's not going to render correctly on modern OS's, where the user has changed the DPI scaling.
In this case it might be better to use the Window SizeToContent property
SizeToContent="WidthAndHeight"
SizeToContent documentation

ResourceDictionaries - StaticResource - other assembly

I'm currently trying to figure out how I can get the WPF designer to display correctly a list of resources I can use.
For example when using a TextBlock in xaml, I can "preview" the useable resources, for usual.
This does not seem to work well when using it from an external DLL/assembly (binary).
I've already tried to use the usual source strings for ResourceDictionary,
<ResourceDictionary Source="pack://application:,,,/MyAssembly;component/Themes/Generic.xaml"/>
<ResourceDictionary Source="/MyAssembly;component/Themes/Generic.xaml"/>
as mentioned in various other questions and answers while googling this issue, though not even the direct Uri to the required ResourceDictionary seems to work.
Is there any fix for this issue or does it simply not work ?
I don't want to disable the designer, please do not suggest so.

How is the default template of a custom control applied with out using "Themes\Generic.xaml ?"

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>

Create custom controls without generic.xaml?

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>

Shared resource dictionary between several user controls and across assemblies

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

Categories

Resources