6

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>
Geertie
  • 237
  • 4
  • 15

2 Answers2

6

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.

kekekeks
  • 3,193
  • 19
  • 16
  • Thanks for the explanation kekekeks ! It would be nice if that was mentioned in the documentation. But I have one more question. Isn't fluent the successor of metro, so microsoft/windows only ? I do not get why it would be different between default and fluent themes ? The only thing I can think of is that in the background avalonia uses fluent on windows only and the default theme on the other platforms, is that a correct assumption ? – Geertie Mar 03 '21 at 08:58
  • OK, I tried it out and for the buttons, this works great (I had to modify some property names, but they can be found in the avalonia/button.xaml file you pointed at. But if I try to do this for for instance a TextBlock, two problems arise : 1 - No TextBlock xaml file in the controls directory (you pointed at), so impossible to know the property names. 2 - If I try for instance , I do not get errors, but it does not work. My property is not overridden. – Geertie Mar 03 '21 at 09:35
  • TextBlock is not a lookless control, so there is no template for it. Rider should show you completions for property names in style setters. For less sophisticated IDEs you can type `TextBlock tb = null; tb.` in your C# editor and it will show you property names as well. – kekekeks Mar 04 '21 at 10:16
  • Thanks again for the answer Kekekeks. I'm using Rider and I do get the suggestions, but I think the main problem is not the IDE but me not knowing enough about xaml. I have a firm background in Winforms, JavaFx, Spring and QML but not in xaml (wpf/uwp). So I will first follow a course on WPF (since it is the closest to avalonia I read) and move over from there to avalonia (I might actually do them side by side WPF in Visual Studio and Avalona in Rider). – Geertie Mar 04 '21 at 11:04
1

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 !

Geertie
  • 237
  • 4
  • 15