diff --git a/samples/ControlCatalog/Pages/ThemePage.axaml.cs b/samples/ControlCatalog/Pages/ThemePage.axaml.cs
index af7b2fe37d..f0ae1a722d 100644
--- a/samples/ControlCatalog/Pages/ThemePage.axaml.cs
+++ b/samples/ControlCatalog/Pages/ThemePage.axaml.cs
@@ -18,7 +18,7 @@ namespace ControlCatalog.Pages
selector.Items = new[]
{
- new ThemeVariant("Default"),
+ ThemeVariant.Default,
ThemeVariant.Dark,
ThemeVariant.Light,
Pink
diff --git a/src/Avalonia.Base/Styling/ThemeVariant.cs b/src/Avalonia.Base/Styling/ThemeVariant.cs
index d9cb123925..8218533f4f 100644
--- a/src/Avalonia.Base/Styling/ThemeVariant.cs
+++ b/src/Avalonia.Base/Styling/ThemeVariant.cs
@@ -5,20 +5,60 @@ using Avalonia.Platform;
namespace Avalonia.Styling;
+///
+/// Specifies a UI theme variant that should be used for the
+///
[TypeConverter(typeof(ThemeVariantTypeConverter))]
-public sealed record ThemeVariant(object Key)
-{
+public sealed record ThemeVariant
+{
+ ///
+ /// Creates a new instance of the
+ ///
+ /// Key of the theme variant by which variants are compared.
+ /// Reference to a theme variant which should be used, if resource wasn't found for the requested variant.
+ /// Thrown if inheritVariant is a reference to the which is ambiguous value to inherit.
+ /// Thrown if key is null.
public ThemeVariant(object key, ThemeVariant? inheritVariant)
- : this(key)
{
+ Key = key ?? throw new ArgumentNullException(nameof(key));
InheritVariant = inheritVariant;
+
+ if (inheritVariant == Default)
+ {
+ throw new ArgumentException("Inheriting default theme variant is not supported.", nameof(inheritVariant));
+ }
}
+ private ThemeVariant(object key)
+ {
+ Key = key;
+ }
+
+ ///
+ /// Key of the theme variant by which variants are compared.
+ ///
+ public object Key { get; }
+
+ ///
+ /// Reference to a theme variant which should be used, if resource wasn't found for the requested variant.
+ ///
+ public ThemeVariant? InheritVariant { get; }
+
+ ///
+ /// Inherit theme variant from the parent. If set on Application, system theme is inherited.
+ /// Using Default as the ResourceDictionary.Key marks this dictionary as a fallback in case the theme variant or resource key is not found in other theme dictionaries.
+ ///
public static ThemeVariant Default { get; } = new(nameof(Default));
+
+ ///
+ /// Use the Light theme variant.
+ ///
public static ThemeVariant Light { get; } = new(nameof(Light));
- public static ThemeVariant Dark { get; } = new(nameof(Dark));
- public ThemeVariant? InheritVariant { get; init; }
+ ///
+ /// Use the Dark theme variant.
+ ///
+ public static ThemeVariant Dark { get; } = new(nameof(Dark));
public override string ToString()
{
@@ -35,7 +75,7 @@ public sealed record ThemeVariant(object Key)
return Key == other?.Key;
}
- public static ThemeVariant FromPlatformThemeVariant(PlatformThemeVariant themeVariant)
+ public static explicit operator ThemeVariant(PlatformThemeVariant themeVariant)
{
return themeVariant switch
{
@@ -45,19 +85,19 @@ public sealed record ThemeVariant(object Key)
};
}
- public PlatformThemeVariant? ToPlatformThemeVariant()
+ public static explicit operator PlatformThemeVariant?(ThemeVariant themeVariant)
{
- if (this == Light)
+ if (themeVariant == Light)
{
return PlatformThemeVariant.Light;
}
- else if (this == Dark)
+ else if (themeVariant == Dark)
{
return PlatformThemeVariant.Dark;
}
- else if (InheritVariant is { } inheritVariant)
+ else if (themeVariant.InheritVariant is { } inheritVariant)
{
- return inheritVariant.ToPlatformThemeVariant();
+ return (PlatformThemeVariant?)inheritVariant;
}
return null;
diff --git a/src/Avalonia.Base/Styling/ThemeVariantTypeConverter.cs b/src/Avalonia.Base/Styling/ThemeVariantTypeConverter.cs
index 4da1b495f5..acb2d7651b 100644
--- a/src/Avalonia.Base/Styling/ThemeVariantTypeConverter.cs
+++ b/src/Avalonia.Base/Styling/ThemeVariantTypeConverter.cs
@@ -15,9 +15,10 @@ public class ThemeVariantTypeConverter : TypeConverter
{
return value switch
{
+ nameof(ThemeVariant.Default) => ThemeVariant.Default,
nameof(ThemeVariant.Light) => ThemeVariant.Light,
nameof(ThemeVariant.Dark) => ThemeVariant.Dark,
- _ => new ThemeVariant(value)
+ _ => throw new NotSupportedException("ThemeVariant type converter supports only build in variants. For custom variants please use x:Static markup extension.")
};
}
}
diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs
index 3dcba4ded9..6d3ba3cf8a 100644
--- a/src/Avalonia.Controls/Application.cs
+++ b/src/Avalonia.Controls/Application.cs
@@ -340,7 +340,7 @@ namespace Avalonia
private void OnColorValuesChanged(object? sender, PlatformColorValues e)
{
- SetValue(ActualThemeVariantProperty, ThemeVariant.FromPlatformThemeVariant(e.ThemeVariant), BindingPriority.Template);
+ SetValue(ActualThemeVariantProperty, (ThemeVariant)e.ThemeVariant, BindingPriority.Template);
}
}
}
diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs
index 7fe82a452e..676fa1519a 100644
--- a/src/Avalonia.Controls/TopLevel.cs
+++ b/src/Avalonia.Controls/TopLevel.cs
@@ -435,7 +435,7 @@ namespace Avalonia.Controls
}
else if (change.Property == ActualThemeVariantProperty)
{
- PlatformImpl?.SetFrameThemeVariant(change.GetNewValue().ToPlatformThemeVariant() ?? PlatformThemeVariant.Light);
+ PlatformImpl?.SetFrameThemeVariant((PlatformThemeVariant?)change.GetNewValue() ?? PlatformThemeVariant.Light);
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
index 365a07a7f6..4068caac21 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
@@ -302,13 +302,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
result = new XamlStaticExtensionNode(new XamlAstObjectNode(node, node.Type), themeVariantTypeRef, foundConstProperty.Name);
return true;
}
-
- result = new XamlAstNewClrObjectNode(node, themeVariantTypeRef, types.ThemeVariantConstructor,
- new List()
- {
- new XamlConstantNode(node, context.Configuration.WellKnownTypes.String, variantText)
- });
- return true;
}
result = null;
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
index a4a3bcce94..16f6a32ae1 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
@@ -69,7 +69,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlType Thickness { get; }
public IXamlConstructor ThicknessFullConstructor { get; }
public IXamlType ThemeVariant { get; }
- public IXamlConstructor ThemeVariantConstructor { get; }
public IXamlType Point { get; }
public IXamlConstructor PointFullConstructor { get; }
public IXamlType Vector { get; }
@@ -193,7 +192,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
FontFamily = cfg.TypeSystem.GetType("Avalonia.Media.FontFamily");
FontFamilyConstructorUriName = FontFamily.GetConstructor(new List { Uri, XamlIlTypes.String });
ThemeVariant = cfg.TypeSystem.GetType("Avalonia.Styling.ThemeVariant");
- ThemeVariantConstructor = ThemeVariant.GetConstructor(new List { XamlIlTypes.String });
(IXamlType, IXamlConstructor) GetNumericTypeInfo(string name, IXamlType componentType, int componentCount)
{
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/ThemeDictionariesTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ThemeDictionariesTests.cs
similarity index 97%
rename from tests/Avalonia.Markup.Xaml.UnitTests/ThemeDictionariesTests.cs
rename to tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ThemeDictionariesTests.cs
index 56040c2186..c5b62cdff2 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/ThemeDictionariesTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ThemeDictionariesTests.cs
@@ -6,10 +6,12 @@ using Avalonia.Styling;
using Moq;
using Xunit;
-namespace Avalonia.Markup.Xaml.UnitTests;
+namespace Avalonia.Markup.Xaml.UnitTests.Xaml;
public class ThemeDictionariesTests : XamlTestBase
{
+ public static ThemeVariant Custom { get; } = new(nameof(Custom), ThemeVariant.Light);
+
[Fact]
public void DynamicResource_Updated_When_Control_Theme_Changed()
{
@@ -353,13 +355,14 @@ public class ThemeDictionariesTests : XamlTestBase
Assert.Equal(Colors.Red, ((ISolidColorBrush)border.Background)!.Color);
}
-
+
[Fact]
public void Custom_Theme_Can_Be_Defined_In_ThemeDictionaries()
{
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
@@ -370,7 +373,7 @@ public class ThemeDictionariesTests : XamlTestBase
White
-
+
Pink
@@ -380,9 +383,9 @@ public class ThemeDictionariesTests : XamlTestBase
");
var border = (Border)themeVariantScope.Child!;
-
- themeVariantScope.RequestedThemeVariant = new ThemeVariant("Custom");
+ themeVariantScope.RequestedThemeVariant = Custom;
+
Assert.Equal(Colors.Pink, ((ISolidColorBrush)border.Background)!.Color);
}