XAML: Background setter is ignored in a CustomControl page - xaml

I created a custom control derived from Page.
namespace The_Toolbox
{
public class BlancoPageControl : Page
{
static BlancoPageControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(BlancoPageControl), new FrameworkPropertyMetadata(typeof(BlancoPageControl)));
}
}
}
In Generic.xaml I can set the foreground color. But for a reason I don't get, I can't set the background color.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:The_Toolbox">
<Style TargetType="{x:Type local:BlancoPageControl}">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="Violet"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BlancoPageControl}">
...
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
TestPage.xaml:
<local:BlancoPageControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:The_Toolbox"
xmlns:res="clr-namespace:The_Toolbox.LocalResources"
mc:Ignorable="d"
x:Class="The_Toolbox.TestPage">
<StackPanel>
....
</StackPanel>
</local:BlancoPageControl>
I would expect the page to get violet, but the color setting is ignored. Why? Of course I could add a border and add the background color in there, but Page also supports background brushses...

Related

AvaloniaUI Styles-pseudoclasses

I'm trying out styles in avalonia and most works, except for pseudoclasses, they just get ignored.
I have created a window and all styles are in there and I have created a user control (with a button on - the pseudoclasses are on the button), using the styles. I do not use code, only xaml to define the styles.
I have tried it out in the "Style Selector" for the button as "Button:pseudoclassname" and "Button.le:pseudoclassname". I have also tried "Button:pointerover" and "Button:hover" as the documentation mentions that that could be modified. No result. The styles for the pseudoclasses are all ignored, the others are all executed correct.
Is there something I'm doing wrong or is this a bug in avalonia ?
The xaml windows file:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:Hub.Views"
xmlns:vm="using:Hub.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Hub.Views.MainWindow"
Icon="/Assets/avalonia-logo.ico"
Width="200" Height="300"
Title="Hub"
Classes="le">
<Window.Styles>
<Style Selector="Window.le">
<Setter Property="Background" Value="#191919"/>
</Style>
<Style Selector="Button.le">
<Setter Property="Background" Value="green"/>
<Setter Property="Foreground" Value="white"/>
</Style>
<Style Selector="Button.le:pointerover">
<Setter Property="Background" Value="red"/>
<Setter Property="Foreground" Value="white"/>
</Style>
<Style Selector="Button.le:pressed">
<Setter Property="Background" Value="blue"/>
<Setter Property="Foreground" Value="white"/>
</Style>
<Style Selector="TextBlock.le_update">
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="FontSize" Value="17"/>
<Setter Property="FontFamily" Value="Arial, Verdana"/>
<Setter Property="Foreground" Value="white"/>
<Setter Property="Background" Value="transparent"/>
</Style>
</Window.Styles>
<views:UpdateView/>
</Window>
The xaml user control file:
<UserControl xmlns="https://github.com/avaloniaui"
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"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Hub.Views.UpdateView">
<DockPanel>
<StackPanel DockPanel.Dock="Bottom">
<Button Classes="le" HorizontalAlignment="Center" HorizontalContentAlignment="Center" Width="300">
Check for updates
</Button>
</StackPanel>
<StackPanel Spacing="5" Margin="5">
<TextBlock Classes="le_update" HorizontalAlignment="Center" Margin="4">
No updates for Hub.
</TextBlock>
<TextBlock Classes="le_update" HorizontalAlignment="Center" Margin="4">
No updates for Engine.
</TextBlock>
</StackPanel>
</DockPanel>
</UserControl>
Button's Background property does get affected by your style, but at that point it has no effect on the actual Button's background, because Background property controls only the normal state of the button.
If you take a look at the default Button style here you can see that it passes its background to ContentPresenter via TemplateBinding:
<Setter Property="Template">
<ControlTemplate>
<ContentPresenter x:Name="PART_ContentPresenter"
Background="{TemplateBinding Background}"
but overrides ContentPresenter's background in a style like this:
<Style Selector="Button:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPointerOver}" />
Since it's ContentPresenter that actually draws the background (Button is a lookless control), you'll see the button to have ButtonBackgroundPointerOver and not the Button's Background property value.
So, you need to write a style that changes the inner ContentPresenter like this:
<Style Selector="Button.le:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="green" />
</Style>
Unfortunately that makes your styles theme-dependent since control templates are different between default and fluent themes.
The answer Kekekeks gave is the correct one for the question I asked.
However, I use this space in the hope to help novice users of avalonia with no background in xaml at all, like I do. Most of us look at avalonia to give our apps an interface that works on Windows/Mac/Linux. To be honest, at the moment of writing, no real alternatives in c# exist.
At this moment Avalonia does have examples and some documentation that is good, but not so for people not really having a background in xaml.
Therefore, go to Udemy or LikedIn.Learning or Youtube or wherever you find a good course on WPF AND AFTER THAT go to the documentation of Avalonia and start playing around.
The similarities that both (Avalonia and WPF) share is enormous !!! And yes it is mentioned a few times in the docs, but a blunt "Do go and learn WPF first if you are new to xaml !" on the frontpage of the documentation would have saved me a fair share of time in trying to find it all out via the website.
Fair is fair, the project still is in beta and the website is already well documented for that stage, so no blame to the team !

ContentDialog: Applying both Style and PrimaryButtonStyle

Gang,
I'm referencing the 16299 version.
I'm trying to set a style for the ContentDialog, and a Style for the PrimaryButton. However, I cannot get both of them working together:
<ContentDialog x:Class="App1.ContentDialog1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
PrimaryButtonText="Button1"
SecondaryButtonText="Button2"
Style="{StaticResource ContentDialogStyle}"
PrimaryButtonStyle="{StaticResource ContentDialogPrimaryButtonStyle}">
<Grid />
</ContentDialog>
This will only apply the "Style" and not the "PrimaryButtonStyle". However, if I remove the "Style" attribute, I then get the PrimaryButtonStyle applied.
I have tried applying the PimaryButtonStyle inside the Style XAML, but that doesn't work either:
<Style TargetType="Button" x:Key="ContentDialogPrimaryButtonStyle">
<Setter Property="Template">
<Setter.Value>
...
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ContentDialog" x:Key="ContentDialogStyle">
<Setter Property="PrimaryButtonStyle" Value="{StaticResource ContentDialogPrimaryButtonStyle}" />
<Setter Property="Template">
<Setter.Value>
...
</Setter.Value>
</Setter>
</Style>
Any ideas how I style the Primary/Secondary buttons inside a ContentDialog that itself has a Style?
Kind regards
Adam
It should be related with your Template in the ContentDialogStyle. We can change both ContentDialogStyle and PrimaryButtonStyle in the xaml, here is a simple example, you can see it. Then you should take a look at your Template in the ContentDialogStyle.
This is the code,
<Style TargetType="Button" x:Key="ContentDialogPrimaryButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Green" BorderThickness="5">
<ContentPresenter Background="Red" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ContentDialog" x:Key="ContentDialogStyle">
<Setter Property="Background" Value="Yellow"/>
</Style>
This is the ContentDialog,
<ContentDialog
...
PrimaryButtonText="Button1"
SecondaryButtonText="Button2"
Style="{StaticResource ContentDialogStyle}"
PrimaryButtonStyle="{StaticResource ContentDialogPrimaryButtonStyle}">
<Grid/>
</ContentDialog>

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>

ThemeResource in Style isn't used when I build my UWP app

I am trying to make a rectangle that changes color after a tapped event. It should cycle between a disabled mode (gray) and the accent color. I am trying to do this using styles. When I use (a shade of) the accent color in the XAML code {ThemeResource SystemControlHighlightAltListAccentHighBrush} it correctly shows the accent color. It also shows the correct colors in the designer (Visual Studio). However, if I use the theme colors in a resource dictionary, it replaces them by grayish or no colors in my app (after build). This is my ResourceDictionary:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:I_have_never">
<!--Disabled-->
<Style TargetType="RelativePanel" x:Key="Disabled">
<Setter Property="Tag">
<Setter.Value>0</Setter.Value>
</Setter>
<Setter Property="Margin">
<Setter.Value>30,15,30,15</Setter.Value>
</Setter>
<Setter Property="Background">
<Setter.Value>{ThemeResource SystemControlBackgroundListLowBrush} </Setter.Value>
</Setter>
</Style>
<!--Enabled-->
<Style TargetType="RelativePanel" x:Key="Enabled">
<Setter Property="Tag">
<Setter.Value>2</Setter.Value>
</Setter>
<Setter Property="Margin">
<Setter.Value>30,15,30,15</Setter.Value>
</Setter>
<Setter Property="Background">
<Setter.Value>{ThemeResource SystemControlHighlightAltListAccentHighBrush}</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
This is my XAML code:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="150" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<RelativePanel Name="Category1"
Grid.Row="0"
Grid.Column="0"
Tapped="ToggleStatus"
Style="{StaticResource Enabled}">
</RelativePanel>
</Grid>
And this is my C# code to toggle between the styles:
private void ToggleStatus(object sender, RoutedEventArgs e)
{
RelativePanel panel = sender as RelativePanel;
if ((string)panel.Tag == "0")
{
panel.Style = (Style)App.Current.Resources["Enabled"]; // Tag = 1
}
else if ((string)panel.Tag == "1")
{
panel.Style = (Style)App.Current.Resources["Disabled"]; // Tag = 2
}
}
In the design view this works great. It nicely shows the grey or accent color backgrounds. However, when I build this, no colors are shown.
It does show colors as long as I use real colors (e.g. Gray) instead of the ThemeResource. It also works if I use the ThemeResource straight in the XAML code (no styles). Why does it only work in the designer? Why does it not work if I use the ThemeResource in the styles? And how could I fix this?
Why does it not work if I use the ThemeResource in the styles? And how could I fix this?
You are using XAML Property Element Usage Syntax to set the extensionUsage (i.e. {ThemeResource} or {StaticResource}) to Setter.Value property in the styles:
<Setter ...>
<Setter.Value>
objectValue
</Setter.Value>
</Setter>
According to the Syntax part of the official documentation Setter.Value property, when setting an extensionUsage (i.e. {ThemeResource} or {StaticResource}) to Setter.Value property in the styles, we should use XAML Attribute Usage Syntax instead of using XAML Property Element Usage Syntax:
<Setter Property="propertyName" Value="extensionUsage"/>
So you should use the following code to set the Background with {ThemeResource} in the styles:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ThemeResourceInStyle">
<!--Disabled-->
<Style TargetType="RelativePanel" x:Key="Disabled">
<Setter Property="Tag">
<Setter.Value>0</Setter.Value>
</Setter>
<Setter Property="Margin">
<Setter.Value>30,15,30,15</Setter.Value>
</Setter>
<!--use XAML Attribute Usage Syntax to set extensionUsage -->
<Setter Property="Background" Value="{ThemeResource SystemControlBackgroundListLowBrush}" />
</Style>
<!--Enabled-->
<Style TargetType="RelativePanel" x:Key="Enabled">
<Setter Property="Tag">
<Setter.Value>1</Setter.Value>
</Setter>
<Setter Property="Margin">
<Setter.Value>30,15,30,15</Setter.Value>
</Setter>
<!--use XAML Attribute Usage Syntax to set extensionUsage -->
<Setter Property="Background" Value="{ThemeResource SystemControlHighlightAltListAccentHighBrush}" />
</Style>
</ResourceDictionary>

Silverlight 4. How to set a ToolTip with controls in a ResourceDictionary file with Style definitions?

I've looked at tens of Q&As, but haven't found the answer to this apparently simple need.
I'm working with Silverlight 4. I want to define a ToolTip WITH CONTROLS IN IT at the ResourceDictionary file that has the Style definitions.
My user control file "UC_Activity.xaml" has:
...
<TextBox Style="{StaticResource Style0}" Name="tb_id" />
...
If my "Styles.xaml" file has
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Style x:Key="Style0" TargetType="TextBox">
<Setter Property="FontSize" Value="12" />
<Setter Property="FontFamily" Value="Portable User Interface" />
<Setter Property="ToolTipService.ToolTip" Value="Long tooltip text here. This WORKS, but part of the text ends up out of the screen." />
</Style>
</ResourceDictionary>
it works, but I can only show simple text as the ToolTip, and if the text is very long, it will end up out of the screen, where it is impossible to be seen. What I want is something like this:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Style x:Key="Style0" TargetType="TextBox">
<Setter Property="FontSize" Value="12" />
<Setter Property="FontFamily" Value="Portable User Interface" />
<Setter Property="ToolTipService.ToolTip">
<Setter.Value>
<StackPanel>
<sdk:Label Content="Short text here."/>
<TextBlock TextWrapping="Wrap" MaxWidth="200" Text="Long text here. This does NOT WORK." />
</StackPanel>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
but it does NOT WORK. It builds ok, but it gives an exception ("Value does not fall within the expected range.") when starting execution.
Please, how can I do it?
Thank you very much.
I had a similar issue, the problem is that it needs to be a DataTemplate so a different instance is added to the visual tree every time its used. I created an attached property for this:
then it can just be used as follows:
<Setter Property="ControlsBehaviours:TooltipTemplate.Template">
<Setter.Value>
<DataTemplate>
<ToolTip Content="tooltip" />
</DataTemplate>
</Setter.Value>
</Setter>
public class TooltipTemplate
{
/// <summary>
/// Template Dependency Property.
/// </summary>
public static readonly DependencyProperty TemplateProperty =
DependencyProperty.RegisterAttached(
"Template",
typeof (DataTemplate),
typeof (TooltipTemplate),
new PropertyMetadata(new PropertyChangedCallback(TemplateChanged)));
public static void SetTemplate(DependencyObject o, DataTemplate value)
{
o.SetValue(TemplateProperty, value);
}
public static DataTemplate GetTemplate(DependencyObject o)
{
return (DataTemplate) o.GetValue(TemplateProperty);
}
private static void TemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ToolTipService.SetToolTip(d, ((DataTemplate)e.NewValue).LoadContent());
}
}