diff --git a/samples/Sandbox/Sandbox.csproj b/samples/Sandbox/Sandbox.csproj
index d2e66988e0..7a57a13529 100644
--- a/samples/Sandbox/Sandbox.csproj
+++ b/samples/Sandbox/Sandbox.csproj
@@ -5,6 +5,7 @@
net6.0
true
true
+
diff --git a/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs b/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs
index 264a86b014..620cd4723d 100644
--- a/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs
+++ b/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs
@@ -127,7 +127,7 @@ namespace Avalonia.Build.Tasks
public bool Execute()
{
- Enum.TryParse(ReportImportance, out _reportImportance);
+ Enum.TryParse(ReportImportance, true, out _reportImportance);
BuildEngine.LogMessage($"GenerateAvaloniaResourcesTask -> Root: {Root}, {Resources?.Count()} resources, Output:{Output}", _reportImportance < MessageImportance.Low ? MessageImportance.High : _reportImportance);
var resources = BuildResourceSources();
diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
index d71070e818..d4c4ae8667 100644
--- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
+++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
@@ -288,6 +288,24 @@ namespace Avalonia.Build.Tasks
if (precompileText != "true")
throw new XamlParseException("Invalid value for x:Precompile", precompileDirective);
}
+
+ var classModifierDirective = initialRoot.Children.OfType()
+ .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "ClassModifier");
+ bool? classModifierPublic = null;
+ if (classModifierDirective != null)
+ {
+ var classModifierText = (classModifierDirective.Values[0] as XamlAstTextNode)?.Text.Trim()
+ .ToLowerInvariant();
+ if ("Public".Equals(classModifierText, StringComparison.OrdinalIgnoreCase))
+ classModifierPublic = true;
+ // XAML spec uses "Public" and "NotPublic" values,
+ // When WPF documentation uses "public" and "internal".
+ else if ("NotPublic".Equals(classModifierText, StringComparison.OrdinalIgnoreCase)
+ || "Internal".Equals(classModifierText, StringComparison.OrdinalIgnoreCase))
+ classModifierPublic = false;
+ else
+ throw new XamlParseException("Invalid value for x:ClassModifier. Expected value are: Public, NotPublic (internal).", precompileDirective);
+ }
var classDirective = initialRoot.Children.OfType()
.FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Class");
@@ -297,8 +315,21 @@ namespace Avalonia.Build.Tasks
if (classDirective.Values.Count != 1 || !(classDirective.Values[0] is XamlAstTextNode tn))
throw new XamlParseException("x:Class should have a string value", classDirective);
classType = typeSystem.TargetAssembly.FindType(tn.Text);
+
if (classType == null)
throw new XamlParseException($"Unable to find type `{tn.Text}`", classDirective);
+
+ var isClassPublic = typeSystem.GetTypeReference(classType).Resolve().IsPublic;
+ classModifierPublic ??= isClassPublic;
+
+ // We do not really need x:ClassModifier support for x:Class, but we can at least use it for validation here.
+ if (classModifierPublic != isClassPublic)
+ {
+ throw new XamlParseException(
+ "XAML file x:ClassModifier doesn't match the x:Class type modifiers.",
+ precompileDirective);
+ }
+
compiler.OverrideRootType(parsed,
new XamlAstClrTypeReference(classDirective, classType, false));
initialRoot.Children.Remove(classDirective);
@@ -312,6 +343,8 @@ namespace Avalonia.Build.Tasks
var classTypeDefinition =
classType == null ? null : typeSystem.GetTypeReference(classType).Resolve();
+ // All XAML files are public by default.
+ classModifierPublic ??= true;
var populateBuilder = classTypeDefinition == null ?
builder :
@@ -319,10 +352,11 @@ namespace Avalonia.Build.Tasks
((List)parsedXamlDocuments).Add(new XamlDocumentResource(
parsed, res.Uri, res, classType,
+ classModifierPublic.Value,
populateBuilder,
compiler.DefinePopulateMethod(populateBuilder, parsed, populateName,
- classTypeDefinition == null),
- buildName == null ? null : compiler.DefineBuildMethod(builder, parsed, buildName, true)));
+ classTypeDefinition == null && classModifierPublic.Value),
+ buildName == null ? null : compiler.DefineBuildMethod(builder, parsed, buildName, classModifierPublic.Value)));
}
catch (Exception e)
{
@@ -368,7 +402,7 @@ namespace Avalonia.Build.Tasks
document.PopulateMethod,
document.BuildMethod,
builder.DefineSubType(compilerConfig.WellKnownTypes.Object, "NamespaceInfo:" + res.Name,
- true),
+ document.IsPublic),
(closureName, closureBaseType) =>
populateBuilder.DefineSubType(closureBaseType, closureName, false),
(closureName, returnType, parameterTypes) =>
@@ -502,7 +536,8 @@ namespace Avalonia.Build.Tasks
}
- if (document.BuildMethod != null || classTypeDefinition != null)
+ if (document.IsPublic
+ && (document.BuildMethod != null || classTypeDefinition != null))
{
var compiledBuildMethod = document.BuildMethod == null ?
null :
diff --git a/src/Avalonia.Themes.Fluent/Accents/BaseColorsPalette.xaml b/src/Avalonia.Themes.Fluent/Accents/BaseColorsPalette.xaml
index 362d543646..620add9045 100644
--- a/src/Avalonia.Themes.Fluent/Accents/BaseColorsPalette.xaml
+++ b/src/Avalonia.Themes.Fluent/Accents/BaseColorsPalette.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Accents/BaseResources.xaml b/src/Avalonia.Themes.Fluent/Accents/BaseResources.xaml
index 517a80fd7e..6f12f1d306 100644
--- a/src/Avalonia.Themes.Fluent/Accents/BaseResources.xaml
+++ b/src/Avalonia.Themes.Fluent/Accents/BaseResources.xaml
@@ -1,7 +1,8 @@
+ xmlns:converters="using:Avalonia.Controls.Converters"
+ x:ClassModifier="internal">
fonts:Inter#Inter, $Default
14
diff --git a/src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml b/src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml
index 61a74f26a4..397f7ec431 100644
--- a/src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml
+++ b/src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj b/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj
index e63a0c9c26..660661fc94 100644
--- a/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj
+++ b/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj
@@ -1,8 +1,6 @@
net6.0;netstandard2.0
-
- $(NoWarn);IL2026
diff --git a/src/Avalonia.Themes.Fluent/Controls/AdornerLayer.xaml b/src/Avalonia.Themes.Fluent/Controls/AdornerLayer.xaml
index c4b91b4822..fefa1ea055 100644
--- a/src/Avalonia.Themes.Fluent/Controls/AdornerLayer.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/AdornerLayer.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
0
2
1
diff --git a/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml b/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml
index 2113ae4cb0..228aeaad17 100644
--- a/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml
@@ -1,6 +1,7 @@
+ xmlns:generic="using:System.Collections.Generic"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/Button.xaml b/src/Avalonia.Themes.Fluent/Controls/Button.xaml
index 126f2c22e0..6c6ca967e7 100644
--- a/src/Avalonia.Themes.Fluent/Controls/Button.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/Button.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml b/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml
index 3ce4730698..095e801d0c 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml
@@ -1,7 +1,8 @@
+ xmlns:converters="using:Avalonia.Controls.Converters"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml b/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml
index 9c66ea9b84..2f4a444529 100644
--- a/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml
@@ -6,7 +6,8 @@
-->
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml
index 76b51ca819..206973b7ee 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml
@@ -5,7 +5,8 @@
// All other rights reserved.
-->
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
index 2a3496b648..4739a5b9c5 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
@@ -1,6 +1,7 @@
+ xmlns:sys="using:System"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml
index 6a57cfacd0..904a234ada 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml
@@ -5,7 +5,8 @@
// All other rights reserved.
-->
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml
index 7276742e7d..3bbef81695 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml
@@ -6,7 +6,8 @@
-->
+ xmlns:sys="using:System"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml b/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml
index 0180c3f395..41d74c6063 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/Carousel.xaml b/src/Avalonia.Themes.Fluent/Controls/Carousel.xaml
index 91e331693e..b94ef9b5d9 100644
--- a/src/Avalonia.Themes.Fluent/Controls/Carousel.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/Carousel.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml b/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml
index 28f8649e2d..fc0a8c7c66 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml b/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml
index bc36ad987e..18bf01ece7 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml
@@ -1,6 +1,7 @@
+ xmlns:sys="using:System"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/ComboBoxItem.xaml b/src/Avalonia.Themes.Fluent/Controls/ComboBoxItem.xaml
index 581cbaf80a..ea55770a51 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ComboBoxItem.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ComboBoxItem.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/ContentControl.xaml b/src/Avalonia.Themes.Fluent/Controls/ContentControl.xaml
index 4caf156366..f277c6f9ae 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ContentControl.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ContentControl.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml b/src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml
index f6900f785f..c8e2873eb6 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
+ xmlns:collections="using:System.Collections"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml
index e71e733eff..58f181bd23 100644
--- a/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml
@@ -7,7 +7,8 @@
+ xmlns:sys="using:System"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/DateTimePickerShared.xaml b/src/Avalonia.Themes.Fluent/Controls/DateTimePickerShared.xaml
index 9d21e6e758..9384eff8f4 100644
--- a/src/Avalonia.Themes.Fluent/Controls/DateTimePickerShared.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/DateTimePickerShared.xaml
@@ -6,7 +6,8 @@
-->
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/DropDownButton.xaml b/src/Avalonia.Themes.Fluent/Controls/DropDownButton.xaml
index 421ba0bb18..438ad6cf18 100644
--- a/src/Avalonia.Themes.Fluent/Controls/DropDownButton.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/DropDownButton.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/EmbeddableControlRoot.xaml b/src/Avalonia.Themes.Fluent/Controls/EmbeddableControlRoot.xaml
index ee51ef8085..1fc931db36 100644
--- a/src/Avalonia.Themes.Fluent/Controls/EmbeddableControlRoot.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/EmbeddableControlRoot.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/Expander.xaml b/src/Avalonia.Themes.Fluent/Controls/Expander.xaml
index 37e9b71185..adaecc71ab 100644
--- a/src/Avalonia.Themes.Fluent/Controls/Expander.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/Expander.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml b/src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml
index 31b0a01b21..deb7d39a89 100644
--- a/src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml
@@ -1,6 +1,7 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/FlyoutPresenter.xaml b/src/Avalonia.Themes.Fluent/Controls/FlyoutPresenter.xaml
index 2dca5b0770..e8c9ed9b2a 100644
--- a/src/Avalonia.Themes.Fluent/Controls/FlyoutPresenter.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/FlyoutPresenter.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
1
diff --git a/src/Avalonia.Themes.Fluent/Controls/GridSplitter.xaml b/src/Avalonia.Themes.Fluent/Controls/GridSplitter.xaml
index ca57eccd13..fc08d6b0b6 100644
--- a/src/Avalonia.Themes.Fluent/Controls/GridSplitter.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/GridSplitter.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml b/src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml
index 19a29b9466..91f9536847 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/Label.xaml b/src/Avalonia.Themes.Fluent/Controls/Label.xaml
index ff6909ee87..237da0bfa3 100644
--- a/src/Avalonia.Themes.Fluent/Controls/Label.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/Label.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml b/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml
index 05bbbe9558..2dde18a523 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/ListBoxItem.xaml b/src/Avalonia.Themes.Fluent/Controls/ListBoxItem.xaml
index fc1d0c5ff1..4e74406c92 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ListBoxItem.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ListBoxItem.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml b/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml
index 8519099a27..374daa7ab5 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml
@@ -1,7 +1,8 @@
+ xmlns:internal="using:Avalonia.Dialogs.Internal"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Themes.Fluent/Controls/Menu.xaml b/src/Avalonia.Themes.Fluent/Controls/Menu.xaml
index e6bbbde632..c1640efa8c 100644
--- a/src/Avalonia.Themes.Fluent/Controls/Menu.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/Menu.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">