Skip to main content
Version: 11.0.x

Pseudoclasses

Overview

Pseudoclasses in Avalonia, similar to those in CSS, are keywords exposed by a Control that indicate a distinct control state in a convenient way for Style Selectors. These states are used to conditionally style controls. For example, a Button could have a different appearance while it's being pressed or a TextBox while it is disabled.

Pseudoclass state is tracked by the Control's PseudoClasses property. By convention, pseudoclass names begin with a :, such as :pointerover or :pressed.

Selector Usage

The following demonstrates how to apply Bold text to a CheckBox when it is checked:

<Window.Styles>
<Style Selector="CheckBox:checked">
<Setter Property="FontWeight" Value="Bold" />
</Style>
</Window.Styles>

<CheckBox Content="Pseudoselectors" />

A Control can have multiple pseudoclasses active and you can target multiple pseudoclasses with a Selector. For example:

<Style Selector="Button.red:focus:pointerover">

The selector above targets Button controls with the red style class, and that have the :focus and the :pointerover pseudoclass state.

General Pseudoclasses

These pseudoclasses are defined by InputElement and are accessible on every Control:

PseudoclassDescription
:disabledThe Control is disabled and cannot be interacted with.
:pointeroverThe Pointer is over the Control as determined by hit testing.
:focusThe Control has focus.
:focus-withinThe Control has focus or contains a descendant that has focus.
:focus-visibleThe Control has focus and should show a visual indicator.

Accessibility

The PseudoClasses collection is a protected property. This accessibility blocks the external setting of existing and custom pseudoclasses via code-behind and attached behavior. As such, customizing must be implemented through inheritance.

Custom Pseudoclass Example

When creating a custom control, you can define custom pseudoclasses to expose control state. The [PseudoClasses] attribute provides information about your pseudoclass to the IDE. This behavior is inherited, so the custom control automatically benefits from pseudoclasses defined and managed by more primitive controls, such as InputElement's :pointerover.

The following example defines and sets pseudoclasses when the pointer is over different regions of a Button.

[PseudoClasses(":left", ":right", ":middle")]
public class AreaButton : Button
{
protected override void OnPointerMoved(PointerEventArgs e)
{
base.OnPointerMoved(e);
var pos = e.GetPosition(this);

if (pos.X < Bounds.Width * 0.25)
SetAreaPseudoclasses(true, false, false);
else if (pos.X > Bounds.Width * 0.75)
SetAreaPseudoclasses(false, true, false);
else
SetAreaPseudoclasses(false, false, true);
}

protected override void OnPointerExited(PointerEventArgs e)
{
base.OnPointerExited(e);
SetAreaPseudoclasses(false, false, false);
}

private void SetAreaPseudoclasses(bool left, bool right, bool middle)
{
PseudoClasses.Set(":left", left);
PseudoClasses.Set(":right", right);
PseudoClasses.Set(":middle", middle);
}
}
warning

StyleKeyOverride is used when creating simple, derived controls with the ControlTheme defined by their parent. In this case since Button is a TemplatedControl, creating a ControlTheme is necessary as the Selector must target AreaButton for the new pseudoclasses.