diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs
index 9ca0b91523..7c57ea3db9 100644
--- a/src/Avalonia.Controls.DataGrid/DataGrid.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs
@@ -24,12 +24,14 @@ using Avalonia.Input.Platform;
using System.ComponentModel.DataAnnotations;
using Avalonia.Controls.Utils;
using Avalonia.Layout;
+using Avalonia.Controls.Metadata;
namespace Avalonia.Controls
{
///
/// Displays data in a customizable grid.
///
+ [PseudoClasses(":invalid")]
public partial class DataGrid : TemplatedControl
{
private const string DATAGRID_elementRowsPresenterName = "PART_RowsPresenter";
diff --git a/src/Avalonia.Controls.DataGrid/DataGridCell.cs b/src/Avalonia.Controls.DataGrid/DataGridCell.cs
index e5fbfa1a81..445dc541a7 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridCell.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridCell.cs
@@ -3,6 +3,7 @@
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
+using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
@@ -12,6 +13,7 @@ namespace Avalonia.Controls
///
/// Represents an individual cell.
///
+ [PseudoClasses(":selected", ":current", ":edited", ":invalid")]
public class DataGridCell : ContentControl
{
private const string DATAGRIDCELL_elementRightGridLine = "PART_RightGridLine";
diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
index 25aae99942..856d1f6566 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
@@ -14,12 +14,14 @@ using Avalonia.Utilities;
using System;
using Avalonia.Controls.Utils;
using Avalonia.Controls.Mixins;
+using Avalonia.Controls.Metadata;
namespace Avalonia.Controls
{
///
/// Represents an individual column header.
///
+ [PseudoClasses(":dragIndicator", ":pressed", ":sortascending", ":sortdescending")]
public class DataGridColumnHeader : ContentControl
{
private enum DragMode
diff --git a/src/Avalonia.Controls.DataGrid/DataGridRow.cs b/src/Avalonia.Controls.DataGrid/DataGridRow.cs
index d5ce8dba75..c3562c53a4 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridRow.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridRow.cs
@@ -3,6 +3,7 @@
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
+using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Controls.Templates;
@@ -20,6 +21,7 @@ namespace Avalonia.Controls
///
/// Represents a row.
///
+ [PseudoClasses(":selected", ":editing", ":invalid")]
public class DataGridRow : TemplatedControl
{
diff --git a/src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs b/src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs
index 0833247439..1e03b134b1 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs
@@ -3,6 +3,7 @@
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
+using Avalonia.Controls.Metadata;
using Avalonia.Controls.Mixins;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
@@ -13,6 +14,7 @@ using System.Reactive.Linq;
namespace Avalonia.Controls
{
+ [PseudoClasses(":pressed", ":current", ":expanded")]
public class DataGridRowGroupHeader : TemplatedControl
{
private const string DATAGRIDROWGROUPHEADER_expanderButton = "ExpanderButton";
diff --git a/src/Avalonia.Controls.DataGrid/DataGridRowHeader.cs b/src/Avalonia.Controls.DataGrid/DataGridRowHeader.cs
index 8f8b1742ba..0cd3589a57 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridRowHeader.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridRowHeader.cs
@@ -3,6 +3,7 @@
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
+using Avalonia.Controls.Metadata;
using Avalonia.Input;
using Avalonia.Media;
using System.Diagnostics;
@@ -12,6 +13,7 @@ namespace Avalonia.Controls.Primitives
///
/// Represents an individual row header.
///
+ [PseudoClasses(":invalid", ":selected", ":editing", ":current")]
public class DataGridRowHeader : ContentControl
{
private const string DATAGRIDROWHEADER_elementRootName = "PART_Root";
diff --git a/src/Avalonia.Controls/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox.cs
index c164f282e8..6bbb4f0b75 100644
--- a/src/Avalonia.Controls/AutoCompleteBox.cs
+++ b/src/Avalonia.Controls/AutoCompleteBox.cs
@@ -14,6 +14,7 @@ using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Collections;
+using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Controls.Utils;
@@ -30,6 +31,7 @@ namespace Avalonia.Controls
///
/// event.
///
+ [PseudoClasses(":dropdownopen")]
public class PopulatedEventArgs : EventArgs
{
///
diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs
index b54eb2ac57..e94d00b2ff 100644
--- a/src/Avalonia.Controls/Button.cs
+++ b/src/Avalonia.Controls/Button.cs
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Windows.Input;
+using Avalonia.Controls.Metadata;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
@@ -28,6 +29,7 @@ namespace Avalonia.Controls
///
/// A button control.
///
+ [PseudoClasses(":pressed")]
public class Button : ContentControl
{
///
diff --git a/src/Avalonia.Controls/ButtonSpinner.cs b/src/Avalonia.Controls/ButtonSpinner.cs
index 44f66d397a..5fe2cf3704 100644
--- a/src/Avalonia.Controls/ButtonSpinner.cs
+++ b/src/Avalonia.Controls/ButtonSpinner.cs
@@ -1,4 +1,5 @@
using System;
+using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Data;
using Avalonia.Input;
@@ -15,6 +16,7 @@ namespace Avalonia.Controls
///
/// Represents a spinner control that includes two Buttons.
///
+ [PseudoClasses(":left", ":right")]
public class ButtonSpinner : Spinner
{
///
diff --git a/src/Avalonia.Controls/Calendar/CalendarButton.cs b/src/Avalonia.Controls/Calendar/CalendarButton.cs
index 80370df145..76af933b55 100644
--- a/src/Avalonia.Controls/Calendar/CalendarButton.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarButton.cs
@@ -3,6 +3,7 @@
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
+using Avalonia.Controls.Metadata;
using Avalonia.Input;
using System;
@@ -12,6 +13,7 @@ namespace Avalonia.Controls.Primitives
/// Represents a button on a
/// .
///
+ [PseudoClasses(":selected", ":inactive", ":btnfocused")]
public sealed class CalendarButton : Button
{
///
diff --git a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs
index 3a39bd10fa..d5748bb9e4 100644
--- a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs
@@ -5,10 +5,12 @@
using System;
using System.Globalization;
+using Avalonia.Controls.Metadata;
using Avalonia.Input;
namespace Avalonia.Controls.Primitives
{
+ [PseudoClasses(":pressed", ":disabled", ":selected", ":inactive", ":today", ":blackout", ":dayfocused")]
public sealed class CalendarDayButton : Button
{
///
diff --git a/src/Avalonia.Controls/Calendar/CalendarItem.cs b/src/Avalonia.Controls/Calendar/CalendarItem.cs
index 0be7c4f67e..e9ea942142 100644
--- a/src/Avalonia.Controls/Calendar/CalendarItem.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarItem.cs
@@ -7,6 +7,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
+using Avalonia.Controls.Metadata;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
@@ -18,6 +19,7 @@ namespace Avalonia.Controls.Primitives
/// Represents the currently displayed month or year on a
/// .
///
+ [PseudoClasses(":calendardisabled")]
public sealed class CalendarItem : TemplatedControl
{
///
diff --git a/src/Avalonia.Controls/Chrome/CaptionButtons.cs b/src/Avalonia.Controls/Chrome/CaptionButtons.cs
index a86cbc271b..cd60130c5b 100644
--- a/src/Avalonia.Controls/Chrome/CaptionButtons.cs
+++ b/src/Avalonia.Controls/Chrome/CaptionButtons.cs
@@ -1,5 +1,6 @@
using System;
using System.Reactive.Disposables;
+using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
#nullable enable
@@ -9,6 +10,7 @@ namespace Avalonia.Controls.Chrome
///
/// Draws window minimize / maximize / close buttons in a when managed client decorations are enabled.
///
+ [PseudoClasses(":minimized", ":normal", ":maximized", ":fullscreen")]
public class CaptionButtons : TemplatedControl
{
private CompositeDisposable? _disposables;
diff --git a/src/Avalonia.Controls/Chrome/TitleBar.cs b/src/Avalonia.Controls/Chrome/TitleBar.cs
index c0c8076dd8..fbddb06952 100644
--- a/src/Avalonia.Controls/Chrome/TitleBar.cs
+++ b/src/Avalonia.Controls/Chrome/TitleBar.cs
@@ -1,5 +1,6 @@
using System;
using System.Reactive.Disposables;
+using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
#nullable enable
@@ -9,6 +10,7 @@ namespace Avalonia.Controls.Chrome
///
/// Draws a titlebar when managed client decorations are enabled.
///
+ [PseudoClasses(":minimized", ":normal", ":maximized", ":fullscreen")]
public class TitleBar : TemplatedControl
{
private CompositeDisposable? _disposables;
diff --git a/src/Avalonia.Controls/DataValidationErrors.cs b/src/Avalonia.Controls/DataValidationErrors.cs
index dfe9a16532..3c64691816 100644
--- a/src/Avalonia.Controls/DataValidationErrors.cs
+++ b/src/Avalonia.Controls/DataValidationErrors.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
+using Avalonia.Controls.Metadata;
using Avalonia.Controls.Templates;
using Avalonia.Data;
@@ -14,6 +15,7 @@ namespace Avalonia.Controls
///
/// You will probably only want to create instances inside of control templates.
///
+ [PseudoClasses(":error")]
public class DataValidationErrors : ContentControl
{
///
diff --git a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs
index a41c159980..8d893154eb 100644
--- a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs
+++ b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs
@@ -1,4 +1,5 @@
-using Avalonia.Controls.Primitives;
+using Avalonia.Controls.Metadata;
+using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Controls.Templates;
using Avalonia.Interactivity;
@@ -11,6 +12,7 @@ namespace Avalonia.Controls
///
/// A control to allow the user to select a date
///
+ [PseudoClasses(":hasnodate")]
public class DatePicker : TemplatedControl
{
///
diff --git a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
index e54da1fb3a..e4ff5e9e5b 100644
--- a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
+++ b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
@@ -1,4 +1,5 @@
-using Avalonia.Controls.Primitives;
+using Avalonia.Controls.Metadata;
+using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Controls.Templates;
using System;
@@ -9,6 +10,7 @@ namespace Avalonia.Controls
///
/// A control to allow the user to select a time
///
+ [PseudoClasses(":hasnotime")]
public class TimePicker : TemplatedControl
{
///
diff --git a/src/Avalonia.Controls/Expander.cs b/src/Avalonia.Controls/Expander.cs
index 43882b70c8..9ff2e41fa9 100644
--- a/src/Avalonia.Controls/Expander.cs
+++ b/src/Avalonia.Controls/Expander.cs
@@ -1,6 +1,6 @@
using Avalonia.Animation;
+using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
-using Avalonia.Data;
namespace Avalonia.Controls
{
@@ -12,6 +12,7 @@ namespace Avalonia.Controls
Right
}
+ [PseudoClasses(":expanded", ":up", ":down", ":left", ":right")]
public class Expander : HeaderedContentControl
{
public static readonly StyledProperty ContentTransitionProperty =
diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs
index a3dfe33641..3aec06e4eb 100644
--- a/src/Avalonia.Controls/ItemsControl.cs
+++ b/src/Avalonia.Controls/ItemsControl.cs
@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using Avalonia.Collections;
using Avalonia.Controls.Generators;
+using Avalonia.Controls.Metadata;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
@@ -18,6 +19,7 @@ namespace Avalonia.Controls
///
/// Displays a collection of items.
///
+ [PseudoClasses(":empty", ":singleitem")]
public class ItemsControl : TemplatedControl, IItemsPresenterHost, ICollectionChangedListener
{
///
diff --git a/src/Avalonia.Controls/ListBoxItem.cs b/src/Avalonia.Controls/ListBoxItem.cs
index e04c79987f..4fe5f4de40 100644
--- a/src/Avalonia.Controls/ListBoxItem.cs
+++ b/src/Avalonia.Controls/ListBoxItem.cs
@@ -1,3 +1,4 @@
+using Avalonia.Controls.Metadata;
using Avalonia.Controls.Mixins;
using Avalonia.Input;
@@ -6,6 +7,7 @@ namespace Avalonia.Controls
///
/// A selectable item in a .
///
+ [PseudoClasses(":pressed", ":selected")]
public class ListBoxItem : ContentControl, ISelectable
{
///
diff --git a/src/Avalonia.Controls/MenuItem.cs b/src/Avalonia.Controls/MenuItem.cs
index b4d3272471..3d8ab3ae48 100644
--- a/src/Avalonia.Controls/MenuItem.cs
+++ b/src/Avalonia.Controls/MenuItem.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Reactive.Linq;
using System.Windows.Input;
using Avalonia.Controls.Generators;
+using Avalonia.Controls.Metadata;
using Avalonia.Controls.Mixins;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
@@ -20,6 +21,7 @@ namespace Avalonia.Controls
///
/// A menu item control.
///
+ [PseudoClasses(":separator", ":icon", ":open", ":pressed", ":selected")]
public class MenuItem : HeaderedSelectingItemsControl, IMenuItem, ISelectable
{
///
diff --git a/src/Avalonia.Controls/Notifications/NotificationCard.cs b/src/Avalonia.Controls/Notifications/NotificationCard.cs
index f90746bf06..cdbace3ced 100644
--- a/src/Avalonia.Controls/Notifications/NotificationCard.cs
+++ b/src/Avalonia.Controls/Notifications/NotificationCard.cs
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Reactive.Linq;
+using Avalonia.Controls.Metadata;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
@@ -9,6 +10,7 @@ namespace Avalonia.Controls.Notifications
///
/// Control that represents and displays a notification.
///
+ [PseudoClasses(":error", ":information", ":success", ":warning")]
public class NotificationCard : ContentControl
{
private bool _isClosed;
diff --git a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
index 6d9f6b8b77..8f5c6faf40 100644
--- a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
+++ b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
@@ -7,12 +7,14 @@ using Avalonia.Controls.Primitives;
using Avalonia.Rendering;
using Avalonia.Data;
using Avalonia.VisualTree;
+using Avalonia.Controls.Metadata;
namespace Avalonia.Controls.Notifications
{
///
/// An that displays notifications in a .
///
+ [PseudoClasses(":topleft", ":topright", ":bottomleft", ":bottomright")]
public class WindowNotificationManager : TemplatedControl, IManagedNotificationManager, ICustomSimpleHitTest
{
private IList _items;
diff --git a/src/Avalonia.Controls/Primitives/ScrollBar.cs b/src/Avalonia.Controls/Primitives/ScrollBar.cs
index 477d24dc99..a7fb7ae08c 100644
--- a/src/Avalonia.Controls/Primitives/ScrollBar.cs
+++ b/src/Avalonia.Controls/Primitives/ScrollBar.cs
@@ -4,6 +4,7 @@ using Avalonia.Interactivity;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Threading;
+using Avalonia.Controls.Metadata;
namespace Avalonia.Controls.Primitives
{
@@ -21,6 +22,7 @@ namespace Avalonia.Controls.Primitives
///
/// A scrollbar control.
///
+ [PseudoClasses(":vertical", ":horizontal")]
public class ScrollBar : RangeBase
{
///
diff --git a/src/Avalonia.Controls/Primitives/Thumb.cs b/src/Avalonia.Controls/Primitives/Thumb.cs
index 96810ed01b..348922b71d 100644
--- a/src/Avalonia.Controls/Primitives/Thumb.cs
+++ b/src/Avalonia.Controls/Primitives/Thumb.cs
@@ -1,9 +1,11 @@
using System;
+using Avalonia.Controls.Metadata;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace Avalonia.Controls.Primitives
{
+ [PseudoClasses(":pressed")]
public class Thumb : TemplatedControl
{
public static readonly RoutedEvent DragStartedEvent =
diff --git a/src/Avalonia.Controls/Primitives/ToggleButton.cs b/src/Avalonia.Controls/Primitives/ToggleButton.cs
index 13031ddad8..f96ca9310d 100644
--- a/src/Avalonia.Controls/Primitives/ToggleButton.cs
+++ b/src/Avalonia.Controls/Primitives/ToggleButton.cs
@@ -1,4 +1,5 @@
using System;
+using Avalonia.Controls.Metadata;
using Avalonia.Data;
using Avalonia.Interactivity;
@@ -7,6 +8,7 @@ namespace Avalonia.Controls.Primitives
///
/// Represents a control that a user can select (check) or clear (uncheck). Base class for controls that can switch states.
///
+ [PseudoClasses(":checked", ":unchecked", ":indeterminate")]
public class ToggleButton : Button
{
///
diff --git a/src/Avalonia.Controls/Primitives/Track.cs b/src/Avalonia.Controls/Primitives/Track.cs
index 29e7f28b44..9399f5fb31 100644
--- a/src/Avalonia.Controls/Primitives/Track.cs
+++ b/src/Avalonia.Controls/Primitives/Track.cs
@@ -4,6 +4,7 @@
// Licensed to The Avalonia Project under MIT License, courtesy of The .NET Foundation.
using System;
+using Avalonia.Controls.Metadata;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Layout;
@@ -12,6 +13,7 @@ using Avalonia.Utilities;
namespace Avalonia.Controls.Primitives
{
+ [PseudoClasses(":vertical", ":horizontal")]
public class Track : Control
{
public static readonly DirectProperty