Xaml Style Child Control in Universal Windows Platform (UWP) - xaml

I would like to know how to set style targetting child controls on the UWP within a style definition.
WPF seems to have 'Style.Resources' to define sub-styles but this doesn't seem the case for UWP
example in wpf : WPF - How to create a style that applies styles to child types

If you want the styles in separate sheets ( which you should. I showed the Styles in the control itself because I misread and thought that's what you wanted ) you can create a Resources folder and add different ResourceDictionaries. Personally I usually create a separate dictionary for Brushes, Styles, Templates, and Converters. Then you declare them in the ResourceDictionary.MergedDictionaries in App.xaml
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
RequestedTheme="Light">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/Brushes.xaml" />
<ResourceDictionary Source="/Resources/Styles.xaml" />
<ResourceDictionary Source="/Resources/Converters.xaml" />
<ResourceDictionary Source="/Resources/Templates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

You can define Styles in the ResourceDictionary of the parent control. The Style defined in Window.Resources applies to all Rectangles because it doesn't specify a Key, so the Rectangle in the first StackPanel is yellow and small. The second StackPanel defines it's own Resources, which its children use, and they end up different colors and a larger size. There's also Style inheritance in there using BasedOn
<Window x:Class="GBTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-GBTest"
mc:Ignorable="d"
Title="MainWindow"
Height="350"
Width="525">
<!--Default style defined in the Window Resources-->
<Window.Resources>
<Style TargetType="Rectangle">
<Setter Property="Width"
Value="100" />
<Setter Property="Height" Value="100" />
<Setter Property="Fill"
Value="Yellow" />
</Style>
</Window.Resources>
<StackPanel>
<Rectangle />
<StackPanel>
<!--The styles defined in the resources of this StckPanel will apply to its children, overriding the default style defined in the Window Resources-->
<StackPanel.Resources>
<Style TargetType="Rectangle"
x:Key="BigStyle">
<Setter Property="Height"
Value="200" />
<Setter Property="Width"
Value="200" />
</Style>
<Style TargetType="Rectangle"
x:Key="RedStyle"
BasedOn="{StaticResource BigStyle}">
<Setter Property="Fill"
Value="Red" />
</Style>
<Style TargetType="Rectangle"
BasedOn="{StaticResource BigStyle}"
x:Key="BlueStyle">
<Setter Property="Fill"
Value="Blue" />
</Style>
</StackPanel.Resources>
<Rectangle Style="{StaticResource RedStyle}" />
<Rectangle Style="{StaticResource BlueStyle}" />
</StackPanel>
</StackPanel>

Related

Using Same MahApps Button Style Twice in Single UserControl Isn't Working

I have a series of button styles (add, edit, delete, etc.) that make use of the MahApps Metro cirucular button style but apply specific images to the button style. When I use any of the styles only once in a UserControl they work just fine and I get the anticipated look from the styles. However, when I use the styles more than once in a single UserControl, only one of the style instances acts as behaved, the others drop the image I am expecting to see.
I have tried naming the specific control instances (in case it was some sort of lifetime management issue) that are using the styles to see if this would fix the issue but it did not. I also tried creating multiple buttons that use the same style properties but do not use the style and that DID work and the buttons showed correctly, but I don't want to go that route as that would defeat the purpose of the styles.
Below is my code for the resource dictionary where I define the button styles. Please note that I have only shown the style for the add button as the other ones are basically the exact same I just change the image type and tool tip. That's why there is the circular button base that I use to define the majority of the style properties.
<!--Reference Dictionaries-->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" /> Source="pack://application:,,,/MahApps.Metro;component/Styles/FlatButton.xaml" />
</ResourceDictionary.MergedDictionaries>
<!--Circular Control Button Base-->
<Style x:Key="CircularControlButtonBase" TargetType="Button" BasedOn="{StaticResource MahApps.Metro.Styles.MetroCircleButtonStyle}">
<Setter Property="Height" Value="30"/>
<Setter Property="Width" Value="30"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{DynamicResource GrayBrush1}"/>
<Setter Property="Foreground" Value="Black"/>
<Style.Triggers>
<!--IsMouseOver Trigger-->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource AccentColorBrush4}"/>
<Setter Property="Foreground" Value="{DynamicResource AccentColorBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource AccentColorBrush}"/>
<Setter Property="BorderThickness" Value="2"/>
</Trigger>
<!--IsEnabled Trigger-->
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource MahApps.Metro.Brushes.Badged.DisabledBackgroundBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
<!--Add Button-->
<Style TargetType="Button" x:Key="AddButton" BasedOn="{StaticResource CircularControlButtonBase}">
<Setter Property="ToolTip" Value="Add"/>
<!--Icon Image-->
<Setter Property="Content">
<Setter.Value>
<Rectangle Width="20" Height="20" Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill">
<VisualBrush.Visual>
<iconPacks:PackIconMaterial Kind="Plus"/>
</VisualBrush.Visual>
</VisualBrush>
</Rectangle.OpacityMask>
</Rectangle>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
And I consume the styles like this.
<UserControl x:Class ="TestClass"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!--The image on this button won't come through.-->
<Button Style="{DynamicResource AddButton}"/>
<!--The image on this button will come through.-->
<Button Style="{DynamicResource AddButton}"/>
</UserControl>
I would expect that the the plus sign image would come through on both buttons, instead of just the last button in the xaml code. Any help would be appreciated.
The IconPacks control inside your style will be only created once. You can use the IconPacks control inside the ControlTemplate and bind to the content which is the enum value to avoid this issue:
<Style x:Key="AddButton"
BasedOn="{StaticResource CircularControlButtonBase}"
TargetType="Button">
<Setter Property="ToolTip" Value="Add"/>
<Setter Property="Content" Value="{x:Static iconPacks:PackIconMaterialKind.Plus}"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<iconPacks:PackIconMaterial Width="20" Height="20" Kind="{Binding}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal">
<Button Style="{DynamicResource AddButton}"/>
<Button Style="{DynamicResource AddButton}"/>
<Button Style="{DynamicResource AddButton}"/>
</StackPanel>
Namespace are:
xmlns:Controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"

UWP Global Resources is overriden by Local Resources even if not the same property

I have an application resource defined in App.xaml. It is tested that the resource applies to the local style if no local resource is defined. So this not some issue like "resource not being initialized".
The code is as below.
App.xaml
<Application
...omitted
RequestedTheme="Light">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Style/DefaultTheme.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
DefaultTheme.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="Button">
<Setter Property="FontSize" Value="50" />
<Setter Property="Background" Value="Red" />
</Style>
</ResourceDictionary>
MainPage.xaml
...omitted
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="Button">
<Setter Property="Width" Value="100" />
<Setter Property="VerticalAlignment" Value="Stretch" />
</Style>
</StackPanel.Resources>
<Button Content="Hello" />
<Button Content="Happy" />
<Button Content="World" />
</StackPanel>
You can see that from the StackPanel's local resources. It is only setting Width and VerticalAlignment while the global dictionary is assigning FontSize and Background. There is no contradiction.
I have also tried this syntax in Xamarin Forms XAML. The local resource will only override global resource when they are assigning the same property. Global resources still apply to the element if not specified.
For more information, ReSharper is having a nice icon saying this "Hides resource from DefaultTheme.xaml ". But when I do this in Xamarin Forms, it will fade out only the properties that are being overridden.
Is there a way to make local resources an add on to global resources in UWP? Assigning x:Key to the global resource then add BasedOn will not be a solution. As I don't think making every button in the app having to derive the global resource make sense in theming.

How to call a Style in a ResourceDictionary file in XAML?

I have a button style in a created style.xaml ResourceDictionary file.
I used this code to call it:
<Button Style="{DynamicResource exitButton}" />
But it didn't recognize the style key either using StaticResource doesn't work too. How to solve this problem?
My style code:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="exitButton" TargetType="Button">
<Setter Property="Width" Value="22"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Background" Value="#FF7070"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock Text="X"
FontSize="15"
Foreground="White"
FontWeight="Bold"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
You have to import the ResourceDictionary file in your xaml, in the Resources tags.
Something like this:
<UserControl blablabla...>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/*PROJECT_NAME*;component/*FOLDER_PATH*/style.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</USerControl.Resources>
<!-- the content -->
...
<Button Style="{StaticResource exitButton}"/>
</UserControl>
You have two options:
As HasNotifications said, embede the resource into the view that you want the style take affect
Embed the style to the application ResourceDictionary. On that case the style will be available to any view on the application
Add the following code to the App.xaml file:
<Application x:Class="WpfApp1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/*PROJECT_NAME*;component/*FOLDER_PATH*/style.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

Cannot find a Resource with the Name / Key

I have a UWP App. The Styles works without a problem when I execute the app. But not in the Designer. Especially User Control can't be loaded. The Error message who is displayed is:
Cannot find a Resource with the Name / Key [Name]
When I go to that User Control it mostly is displayed correctly.
I reference the style with:
Style="{StaticResource DeemphasizedBodyTextBlockStyle}"
I have a file for my Textstyles. In that file I have the style defined as followed:
<Style x:Key="DeemphasizedBodyTextBlockStyle"
TargetType="TextBlock"
BasedOn="{StaticResource BodyTextBlockStyle}">
<Setter Property="FontSize"
Value="12" />
<Setter Property="TextWrapping"
Value="NoWrap" />
<Setter Property="CharacterSpacing"
Value="75" />
<Setter Property="HorizontalAlignment"
Value="Left" />
<Setter Property="VerticalAlignment"
Value="Top" />
<Setter Property="Foreground"
Value="{StaticResource AppForegroundColorSecondary}" />
</Style>
And in the properties of the view project I have a Designer Resource file added (as page) with the following content:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx:///Style/AppStyles.xaml" />
<ResourceDictionary Source="ms-appx:///Style/ColorsDark.xaml" />
<ResourceDictionary Source="ms-appx:///Style/ColorsLight.xaml" />
<ResourceDictionary Source="ms-appx:///Style/ControlStyles.xaml" />
<ResourceDictionary Source="ms-appx:///Style/TextStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
The whole repo is available here: https://github.com/MoneyFox/MoneyFox

FontFamily defined in XAML per platform

In my Xamarin Forms project I would like to define the Form family onect per platform and the use that in the application.
So far I've hardcoded the FontFamily per controltype
<Style x:Key="TahomaBase_Label" TargetType="Label" BaseResourceKey="SubtitleStyle">
<Setter Property="FontFamily" Value="Tahoma" />
...
</Style>
Is it posible to set Fotnfamily globally in my XAML code preferable itn a OnPlatform tag?
Define a style in the App.xaml and then reference that style throughout the app. That way you can set the font once in the App.xaml using the OnPlatform tag and never have to worry about OnPlatform in all your other XAML files.
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="PlatformFontSample.App">
<Application.Resources>
<ResourceDictionary>
<OnPlatform x:Key="FontFamilyName" x:TypeArguments="x:String" iOS="MarkerFelt-Thin" Android="OpenSans" WinPhone="Segoe UI" />
<Style x:Key="FontLabel" TargetType="Label">
<Setter Property="FontFamily" Value="{DynamicResource FontFamilyName}" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
And then:
<Label Text="{Binding Name}" Style="{DynamicResource FontLabel}" FontSize="Medium" FontAttributes="Bold" LineBreakMode="NoWrap"/>