Wpf ResourceDictionary for Style and Brushes and how to MergedDictionaries - wpf

I hope someone can clarify the situation I have below.
I have a simple CustomControl style based on a Button in a ResourceDictionary named SHButtonStyle.xaml
<Style TargetType="{x:Type local:SHButton}">
<Setter Property="Background" Value="{StaticResource ResourceKey= Background}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:SHButton}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I also have a ResourceDictionary named Brushes as below:
<SolidColorBrush x:Key="Background" Color="Red"/>
I also have a Themes folder with Generic.xaml which has the MergedDictionaries as below:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/TestCustomControl;component/SHButtonStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
I have tried merging the ResourceDictionary for the Brushes within the Generic.xaml as I understood it is best to merge all ResourceDictionary's within Generic.xaml?
But the only way I can get this to work is with an additional MergedDictionaries for the Brushes within the SHButtonStyle.xaml. Is this correct or what am I missing when merging the ResourceDictionary's within the Generic.xaml.
Thank you in advance for your assistance

Either merge the brushes resource dictionary in theme/generic.xaml directly, or merge them both at global level in App.xaml:
<Application x:Class="WpfApp1.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="/TestCustomControl;component/Brushes.xaml"/>
<ResourceDictionary Source="/TestCustomControl;component/themes/generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
The MergedDictionaries of themes/generic.xaml usually contains "standalone" resource dictionaries for custom controls without any dependencies to resources in other resource dictionaries.

Related

using a Brush stored in a ResourceDictionary

I am a WPF newbie and I want to create a program wide Brush that I can reference again and again. I have a brush in a ResourceDicitonary with full definition.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options">
<DrawingBrush x:Key="rg1024_metal_effect" Stretch="Uniform">
I have added this to app.xaml.
<Color x:Key="SteelBrush">#FFFFFF</Color>
<SolidColorBrush x:Key="AppBrush" Color="{StaticResource rg1024_metal_effect}"/>
But I get the error:
"rg1024_metal_effect could not be resolved"
I know this should be easy but for a freshie like me - that's not so easy.
If you define a resource in a ResourceDictionary named for example "Dictionary1.xaml" and you want to reference this resource from another resource that you define in another ResourceDictionary, such as for example App.xaml, you should merge Dictionary1.xaml into App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="AppBrush" Color="{StaticResource SteelBrush}"/>
</ResourceDictionary>
</Application.Resources>
Dictionary1.xaml:
<Color x:Key="SteelBrush">#FFFFFF</Color>
In your example, rg1024_metal_effect is not a Color but a DrawingBrush though. You can't set the Color property of a SolidColorBrush to a DrawingBrush.
If you want to use a Color in AppBrush, you'll need to define it like <SolidColorBrush x:Key="AppBrush" Color="{StaticResource SteelBrush}"/>
If you would like to add this brush to button, you can use the same way, like <Button Background="{StaticResource SteelBrush}"/> or create s Style for Button in your resource dictionary
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}" x:Key="StyleKey">
<Setter Property="Background" Value="{StaticResource SteelBrush}"/>
…
</Style>

Exception: Cannot find resource named '*'. Resource names are case sensitive

But why. I see to be correct how the file works:
Error in IFocus.xaml but the converter is defined before.
I don't understant what is wrong.
Referance: Modern.xaml
Is a referance from another project. and i like this.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:Modern.Converters">
<SolidColorBrush x:Key="C_FocusBush" Color="Red"/>
<c:ThicknessConverter x:Key="ThicknessConverter"/>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Interfaces/IFocus/IFocus.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
The IFocus.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:Modern.Interfaces">
<Style TargetType="{x:Type i:IFocus}" x:Key="{x:Type i:IFocus}">
<Setter Property="BorderBrush" Value="{DynamicResource C_FocusBush}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type i:IFocus}">
<Grid Margin="{TemplateBinding Padding}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness, Converter={StaticResource ThicknessConverter}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
The main app to include all resources:
<Application x:Class="*.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:,,,/Modern;component/Modern.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
The brush works fine but the Converter not, why not?
I encountered an error format the same like this after I changed my Visual Studio theme to custom (mine's OneMonokai). I just reverted it back to the default theme and surprisingly it was resolved. It may seem far from the question but you could try this fix if you want.
Since it is the Style in IFocus.xaml that references a Brush resource in Modern.xaml, it's IFocus.xaml that should merge Modern.xaml and not the other way around:
Modern.xaml:
<ResourceDictionary ...>
<SolidColorBrush x:Key="C_FocusBush" Color="Red"/>
</ResourceDictionary>
IFocus.xaml:
<ResourceDictionary ...>
<Style ...>
<Setter Property="BorderBrush" Value="{StaticResource C_FocusBush}"/>
</Style>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Modern.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
App.xaml:
<ResourceDictionary Source="pack://application:,,,/Modern;component/Interfaces/IFocus/IFocus.xaml"/>
Alternatively, you can create a separate resource dictionary with all brushes and merge this one and the one with the styles into App.xaml or another resource dictonary.
You may also want to see my answer here for more information about the order in which resource dictionaries are loaded.

Type converter in WPF Custom Control

I am creating a custom control in WPF and would like to have my converters in a separate resource dictionary to make things cleaner. I have a ControlStyling.xaml resource dictionary for the styling of my controls
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DialIndicatorControl">
<Style TargetType="{x:Type local:MyDialIndicator}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyDialIndicator}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Ellipse Width="{TemplateBinding BackgroundSizeRadius}"
</Ellipse>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
A Converters.xaml resource dictionary where I would like to keep my converteres
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DialIndicatorControl">
<local:RadiusDiameterConverter x:Key="RadiusConvert"/>
And the Themes/Generic.xaml where I am pointing to both of these dictionaries.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DialIndicatorControl">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/DialIndicatorControl;component/Themes/Generic/Converters.xaml"/>
<ResourceDictionary Source="/DialIndicatorControl;component/Themes/Generic/ControlStyling.xaml"/>
</ResourceDictionary.MergedDictionaries>
The problem I am having is when I place my converters in a separate resource dictionary my ControlStyling.xaml dictionary doesn't have a reference to the converters (which seems obvious now that I think about it). I thought that I would be able to use these converters since I merged both dictionaries in my Themes/Generic.xaml dictionary but that didn't work. Is there a good way to have all my converters in a separate dictionary and still be able to reference them in my ControlStyling.xaml for this custom control?
Reference the converter resource dictionary from the styling dictionary:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/DialIndicatorControl;component/Themes/Generic/Converters.xaml"/>
</ResourceDictionary.MergedDictionaries>

My Two DataGrid XAML Resources are Mutually Exclusive --- Why?

In order to have a nicer look, I am trying to add to my DataGrid 2 features that I found in separate places, but for some reason they just can't get along.
I can either have the section inside the blue rectangle or the one in the red one.
TIA
Put the <ControlTemplate> tag inside the <ResourceDictionary> tag, underneath the closing </ResourceDictionary.MergedDictionaries> tag.
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes\DataGrid.Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
<ControlTemplate x:Key="SelectAllButtonTemplate" TargetType="{x:Type Button}">
<Grid>
<Rectangle x:Name="Border" Fill="LightBlue" SnapsToDevicePixels="True" />
</Grid>
</ControlTemplate>
</ResourceDictionary>
</UserControl.Resources>

WPF Custom Control Template Not Applied

I'm sure this question or derivatives of it have been asked a bazillion times, but I couldn't find anything that helped me solve the problem, so I'm asking. Please feel free to direct me to the duplicate that I'm sure exists but I can't find. Apparently I'm not so great with keywords.
I have a Custom Control, it has it's own Resource Dictionary used only to define the control template. This dictionary is then merged into Generic.xaml.
The problem is that when this control shows up in the UI, it has nothing inside of it. I used Snoop to find this out. The control is in the UI, but it is completely empty.
Below you'll find the items that I think are responsible for the problem. Any help or advice you can offer is greatly appreciated.
The relevant parts of my folder structure are like this:
BasicTemplate.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFSpecBuilder.Layouts.Templates">
<Style TargetType="{x:Type local:BasicTemplate}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BasicTemplate}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<TextBlock Text="This is a basic template." />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Generic.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Layouts/Templates/XAML/BasicTemplate.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Try this:
Set Build Action to BasicTemplate.xaml to Page.
Add reference to BasicTemplate.xaml in Generic.xaml:
ResourceDictionary Source="/WPDSpecBuilder;component/Layouts/Templates/Xaml/BasicTemplate.xaml"
It should works.
I think this may be as simple as changing the relative path of the merged dictionary. Try adding a / to the start of the folder path:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Layouts/Templates/XAML/BasicTemplate.xaml" />
</ResourceDictionary.MergedDictionaries>
Try:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WPDSpecBuilder;component/Layouts/Templates/XAML/BasicTemplate.xaml" />
</ResourceDictionary.MergedDictionaries>
See here for more details on Pack Uri's

Resources