diff --git a/Directory.Build.props b/Directory.Build.props
index 84ba0b7c69db..f3f7b152b802 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,6 +2,16 @@
+
+
+
+ <_MauiXamlSourceGenBackCompat>true
+ $(DefineConstants);_MAUIXAML_SOURCEGEN_BACKCOMPAT
+
+
true
diff --git a/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Colors.xaml b/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Colors.xaml
index 30307a5ddc3b..d57fcc6e3987 100644
--- a/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Colors.xaml
+++ b/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Colors.xaml
@@ -1,5 +1,4 @@
-
diff --git a/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Styles.xaml b/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Styles.xaml
index 15a426f62f82..6590af989c48 100644
--- a/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Styles.xaml
+++ b/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Styles.xaml
@@ -1,5 +1,4 @@
-
diff --git a/src/Controls/src/Build.Tasks/XamlCTask.cs b/src/Controls/src/Build.Tasks/XamlCTask.cs
index e5a346c6fa33..30da79f740a8 100644
--- a/src/Controls/src/Build.Tasks/XamlCTask.cs
+++ b/src/Controls/src/Build.Tasks/XamlCTask.cs
@@ -203,88 +203,50 @@ public override bool Execute(out IList thrownExceptions)
using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(IOPath.GetFullPath(Assembly), readerParameters))
{
- CustomAttribute xamlProcessingAttr = null;
- if (assemblyDefinition.HasCustomAttributes &&
- (xamlProcessingAttr =
- assemblyDefinition.CustomAttributes.FirstOrDefault(
- ca => ca.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute")) != null)
- {
- var inflator = (XamlInflator)xamlProcessingAttr.ConstructorArguments[0].Value;
- var generateInflatorSwitch = xamlProcessingAttr.ConstructorArguments.Count > 1
- && (bool)xamlProcessingAttr.ConstructorArguments[1].Value;
- assemblyInflatorOptions = (generateInflatorSwitch, inflator);
- if (!generateInflatorSwitch)
- skipassembly = (inflator & XamlInflator.XamlC) != XamlInflator.XamlC && inflator != XamlInflator.Default;
-
- }
-
-#pragma warning disable CS0618 // Type or member is obsolete
+#if _MAUIXAML_SOURCEGEN_BACKCOMPAT
CustomAttribute xamlcAttr = null;
if (assemblyDefinition.HasCustomAttributes &&
(xamlcAttr =
assemblyDefinition.CustomAttributes.FirstOrDefault(
ca => ca.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.XamlCompilationAttribute")) != null)
{
- if (xamlProcessingAttr == null)
- {
- var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value;
- if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip)
- skipassembly = true;
- if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile)
- skipassembly = false;
- }
- else
- LoggingHelper.LogWarning($"{new string(' ', 2)}Assembly has both XamlCompilationAttribute and XamlProcessingAttribute. XamlCompilationAttribute will be ignored.");
+ var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value;
+ if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip)
+ skipassembly = true;
+ if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile)
+ skipassembly = false;
}
-#pragma warning restore CS0618 // Type or member is obsolete
- xamlcAttr = xamlProcessingAttr = null;
+ xamlcAttr = null;
+#endif
foreach (var module in assemblyDefinition.Modules)
{
var skipmodule = skipassembly;
(bool, XamlInflator)? moduleInflatorOptions = assemblyInflatorOptions;
- if (module.HasCustomAttributes &&
- (xamlProcessingAttr =
- module.CustomAttributes.FirstOrDefault(
- ca => ca.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute")) != null)
- {
- var inflator = (XamlInflator)xamlProcessingAttr.ConstructorArguments[0].Value;
- var generateInflatorSwitch = xamlProcessingAttr.ConstructorArguments.Count > 1
- && (bool)xamlProcessingAttr.ConstructorArguments[1].Value;
- moduleInflatorOptions = (generateInflatorSwitch, inflator);
- if (!generateInflatorSwitch)
- skipmodule = (inflator & XamlInflator.XamlC) != XamlInflator.XamlC && inflator != XamlInflator.Default;
- }
-
-#pragma warning disable CS0618 // Type or member is obsolete
+#if _MAUIXAML_SOURCEGEN_BACKCOMPAT
if (module.HasCustomAttributes &&
(xamlcAttr =
module.CustomAttributes.FirstOrDefault(
ca => ca.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.XamlCompilationAttribute")) != null)
{
- if (xamlProcessingAttr == null)
- {
-
- var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value;
- if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip)
- skipmodule = true;
- if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile)
- skipmodule = false;
- }
- else
- LoggingHelper.LogWarning($"{new string(' ', 2)}Module {module.Name} has both XamlCompilationAttribute and XamlProcessingAttribute. XamlCompilationAttribute will be ignored.");
+ var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value;
+ if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip)
+ skipmodule = true;
+ if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile)
+ skipmodule = false;
}
-#pragma warning restore CS0618 // Type or member is obsolete
-
- xamlcAttr = xamlProcessingAttr = null;
+ xamlcAttr = null;
+#endif
LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Module: {module.Name}");
var resourcesToPrune = new List();
foreach (var resource in module.Resources.OfType())
{
- var initCompName = "InitializeComponent";
+ var generateInflatorSwitch = module.Assembly.Name.Name == "Microsoft.Maui.Controls.Xaml.UnitTests";
+ var initCompName = generateInflatorSwitch ? "InitializeComponentXamlC" : "InitializeComponent";
+
LoggingHelper.LogMessage(Low, $"{new string(' ', 4)}Resource: {resource.Name}");
string classname;
if (!resource.IsXaml(cache, module, out classname))
@@ -301,53 +263,27 @@ public override bool Execute(out IList thrownExceptions)
var skiptype = skipmodule;
(bool, XamlInflator)? typeInflatorOptions = moduleInflatorOptions;
- if (typeDef.HasCustomAttributes &&
- (xamlProcessingAttr =
- typeDef.CustomAttributes.FirstOrDefault(
- ca => ca.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute")) != null)
- {
- var inflator = (XamlInflator)xamlProcessingAttr.ConstructorArguments[0].Value;
- var generateInflatorSwitch = xamlProcessingAttr.ConstructorArguments.Count > 1
- && (bool)xamlProcessingAttr.ConstructorArguments[1].Value;
-
- typeInflatorOptions = (generateInflatorSwitch, inflator);
- if (generateInflatorSwitch)
- {
- skiptype = (inflator & XamlInflator.XamlC) != XamlInflator.XamlC && inflator != XamlInflator.Default;
- initCompName = "InitializeComponentXamlC";
- }
- else
- skiptype = inflator != XamlInflator.XamlC;
- }
-#pragma warning disable CS0618 // Type or member is obsolete
+#if _MAUIXAML_SOURCEGEN_BACKCOMPAT
if (typeDef.HasCustomAttributes &&
(xamlcAttr =
typeDef.CustomAttributes.FirstOrDefault(
ca => ca.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.XamlCompilationAttribute")) != null)
{
- if (xamlProcessingAttr == null)
- {
- // XamlCompilationAttribute is obsolete, but we still need to support it
- // for backwards compatibility
- var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value;
- if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip)
- skiptype = true;
- if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile)
- skiptype = false;
- }
- else
- LoggingHelper.LogWarning($"{new string(' ', 6)}Type {typeDef.Name} has both XamlCompilationAttribute and XamlProcessingAttribute. XamlCompilationAttribute will be ignored.");
+ var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value;
+ if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip)
+ skiptype = true;
+ if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile)
+ skiptype = false;
}
-#pragma warning restore CS0618 // Type or member is obsolete
-
- xamlcAttr = xamlProcessingAttr = null;
+ xamlcAttr = null;
+#endif
if (Type != null)
skiptype = !(Type == classname);
if (skiptype && !ForceCompile)
{
- LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}has XamlCompilation or XamlProceesing disabling XamlC... skipped.");
+ LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}has XamlCompilation disabling XamlC... skipped.");
continue;
}
diff --git a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.Common.targets b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.Common.targets
index 0c33a0cf414f..cffdc4ad2ca5 100644
--- a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.Common.targets
+++ b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.Common.targets
@@ -22,6 +22,14 @@
+
+
+
+
+
+
+
+
+
-
diff --git a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets
index 7f9ead91c76f..493a87b53efd 100644
--- a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets
+++ b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets
@@ -6,6 +6,11 @@
true
True
True
+
+ <_MauiXamlInflator Condition="' $(MauiXamlInflator)' != '' ">$(MauiXamlInflator)
+ <_MauiXamlInflator Condition=" '$(MauiXamlInflator)' == '' And '$(Configuration)' == 'Debug' ">Runtime
+ <_MauiXamlInflator Condition=" '$(MauiXamlInflator)' == '' And '$(Configuration)' != 'Debug' ">XamlC
+
true
@@ -73,11 +78,34 @@
Condition="'$(_XFTargetsImported)' == 'true'"/>
+
+
+
+
+
+
+ <_MauiXaml_SG Remove="@(_MauiXaml_SG)" />
+ <_MauiXaml_RT Remove="@(_MauiXaml_RT)" />
+ <_MauiXaml_XC Remove="@(_MauiXaml_XC)" />
+ <_MauiXaml_SG Include="@(MauiXaml)" Condition="$([System.String]::new('%(MauiXaml.Inflator)').Contains('SourceGen', StringComparison.OrdinalIgnoreCase))" />
+ <_MauiXaml_RT Include="@(MauiXaml)" Condition="$([System.String]::new('%(MauiXaml.Inflator)').Contains('Runtime', StringComparison.OrdinalIgnoreCase))" />
+ <_MauiXaml_XC Include="@(MauiXaml)" Condition="$([System.String]::new('%(MauiXaml.Inflator)').Contains('XamlC', StringComparison.OrdinalIgnoreCase))" />
+ <_MauiXaml_AsEmbeddedResource Include="@(_MauiXaml_RT)" />
+ <_MauiXaml_AsEmbeddedResource Include="@(_MauiXaml_XC)" KeepDuplicates="false" />
+
+
+
+ <_MauiInjectXamlCssAdditionalFilesDependsOn>
+ _MauiXamlComputeInflator;
+ $(CreateManifestResourceNamesDependsOn);
+
+
+
+ DependsOnTargets="$(_MauiInjectXamlCssAdditionalFilesDependsOn)">
<_MauiXamlWithResourceNames Remove="@(_MauiXamlWithResourceNames)" />
<_MauiXamlWithTargetPath Remove="@(_MauiXamlWithTargetPath)" />
@@ -113,6 +141,7 @@
TargetPath="%(_MauiXamlWithResourceNames.TargetPath)"
RelativePath="$([MSBuild]::MakeRelative($(MSBuildProjectDirectory), %(_MauiXamlWithResourceNames.TargetPath)))"
ItemSpec="%(_MauiXamlWithResourceNames.OriginalItemSpec)"
+ Inflator="%(_MauiXamlWithResourceNames.Inflator)"
GenKind="Xaml"/>
-
+
_MauiAddXamlEmbeddedResources;
$(PrepareResourcesDependsOn);
+ <_MauiAddXamlEmbeddedResourcesDependsOn>
+ _MauiXamlComputeInflator
+
-
+
+
diff --git a/src/Controls/src/SourceGen/CodeBehindCodeWriter.cs b/src/Controls/src/SourceGen/CodeBehindCodeWriter.cs
index 51a633b4c269..fa901e5f271e 100644
--- a/src/Controls/src/SourceGen/CodeBehindCodeWriter.cs
+++ b/src/Controls/src/SourceGen/CodeBehindCodeWriter.cs
@@ -69,16 +69,25 @@ public static string GenerateXamlCodeBehind(XamlProjectItemForCB? xamlItem, Comp
}
var rootSymbol = compilation.GetTypeByMetadataName($"{rootClrNamespace}.{rootType}");
+ bool alreadyHasXamlCompilationAttribute = rootSymbol?.GetAttributes().Any(a => a.AttributeClass != null && a.AttributeClass.Equals(compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Xaml.XamlCompilationAttribute")!, SymbolEqualityComparer.Default)) ?? false;
- (var generateInflatorSwitch, var xamlInflators, _) = rootSymbol?.GetXamlProcessing() ?? (false, XamlInflator.Default, false);
+ var generateInflatorSwitch = compilation.AssemblyName == "Microsoft.Maui.Controls.Xaml.UnitTests";
+ var xamlInflators = projItem.Inflator;
+
+ //if there's only the XamlC inflator, prevent non-assigned errors
+ if (xamlInflators == XamlInflator.XamlC)
+ sb.AppendLine("#pragma warning disable CS0649");
sb.AppendLine($"namespace {rootClrNamespace}");
sb.AppendLine("{");
sb.AppendLine($"\t[global::Microsoft.Maui.Controls.Xaml.XamlFilePath(\"{projItem.RelativePath?.Replace("\\", "\\\\")}\")]");
- if (addXamlCompilationAttribute)
- {
+
+#if !_MAUIXAML_SOURCEGEN_BACKCOMPAT
+ if (addXamlCompilationAttribute && !alreadyHasXamlCompilationAttribute)
sb.AppendLine($"\t[global::Microsoft.Maui.Controls.Xaml.XamlCompilation(global::Microsoft.Maui.Controls.Xaml.XamlCompilationOptions.Compile)]");
- }
+#endif
+ if (!addXamlCompilationAttribute && (xamlInflators & XamlInflator.XamlC) == 0 && !alreadyHasXamlCompilationAttribute)
+ sb.AppendLine($"\t[global::Microsoft.Maui.Controls.Xaml.XamlCompilation(global::Microsoft.Maui.Controls.Xaml.XamlCompilationOptions.Skip)]");
if (hideFromIntellisense)
{
@@ -95,10 +104,7 @@ public static string GenerateXamlCodeBehind(XamlProjectItemForCB? xamlItem, Comp
if (generateDefaultCtor)
{
sb.AppendLine($"\t\t[global::System.CodeDom.Compiler.GeneratedCode(\"Microsoft.Maui.Controls.SourceGen\", \"1.0.0.0\")]");
- sb.AppendLine($"\t\tpublic {rootType}()");
- sb.AppendLine("\t\t{");
- sb.AppendLine(generateInflatorSwitch ? "\t\t\tInitializeComponent(global::Microsoft.Maui.Controls.Xaml.XamlInflator.Default);" : "\t\t\tInitializeComponent();");
- sb.AppendLine("\t\t}");
+ sb.AppendLine($"\t\tpublic {rootType}() => InitializeComponent();");
sb.AppendLine();
}
@@ -137,33 +143,22 @@ public static string GenerateXamlCodeBehind(XamlProjectItemForCB? xamlItem, Comp
// - InitializeComponentXamlC will be used for XamlC
// - InitializeComponentSourceGen will be used for SourceGen
// - no parameterless InitializeComponent will be generated
-
if (!generateInflatorSwitch)
{
- if (xamlInflators == XamlInflator.Default)
- {
- if (projItem.Configuration != null && projItem.Configuration.Equals("Release", StringComparison.OrdinalIgnoreCase))
- InitComp("InitializeComponent", empty: true);
- else
- InitComp("InitializeComponent");
- }
if ((xamlInflators & XamlInflator.Runtime) == XamlInflator.Runtime)
InitComp("InitializeComponent");
else if ((xamlInflators & XamlInflator.XamlC) == XamlInflator.XamlC)
- InitComp("InitializeComponent", empty: true);
+ InitComp("InitializeComponent");
else if ((xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen)
InitComp("InitializeComponent", partialsignature: true);
}
else
{
- if ((xamlInflators & XamlInflator.Runtime) == XamlInflator.Runtime
- || xamlInflators == XamlInflator.Default)
+ if ((xamlInflators & XamlInflator.Runtime) == XamlInflator.Runtime)
InitComp("InitializeComponentRuntime");
- if ((xamlInflators & XamlInflator.XamlC) == XamlInflator.XamlC
- || xamlInflators == XamlInflator.Default)
+ if ((xamlInflators & XamlInflator.XamlC) == XamlInflator.XamlC)
InitComp("InitializeComponentXamlC", empty: true);
- if ((xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen
- || xamlInflators == XamlInflator.Default)
+ if ((xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen)
InitComp("InitializeComponentSourceGen", partialsignature: true);
}
@@ -175,11 +170,8 @@ void InitComp(string methodName, bool empty = false, bool partialsignature = fal
if (namedFields != null && namedFields.Any())
{
sb.AppendLine($"#if NET5_0_OR_GREATER");
- foreach ((var fname, _, _) in namedFields)
- {
-
+ foreach ((var fname, _, _) in namedFields)
sb.AppendLine($"\t\t[global::System.Diagnostics.CodeAnalysis.MemberNotNullAttribute(nameof({EscapeIdentifier(fname)}))]");
- }
sb.AppendLine($"#endif");
}
@@ -238,36 +230,40 @@ void InitComp(string methodName, bool empty = false, bool partialsignature = fal
sb.AppendLine($"#endif");
}
- sb.AppendLine($"\t\tprivate void InitializeComponent() => InitializeComponentRuntime();");
- sb.AppendLine();
+
+ //this isn't supposed to be used, so the default to the first available inflator
+ if ((xamlInflators & XamlInflator.Runtime) == XamlInflator.Runtime)
+ sb.AppendLine($"\t\tprivate void InitializeComponent() => InitializeComponentRuntime();");
+ else if ((xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen)
+ sb.AppendLine($"\t\tprivate void InitializeComponent() => InitializeComponentSourceGen();");
+ else if ((xamlInflators & XamlInflator.XamlC) == XamlInflator.XamlC)
+ sb.AppendLine($"\t\tprivate void InitializeComponent() => InitializeComponentXamlC();");
+
sb.AppendLine($"\t\t[global::System.CodeDom.Compiler.GeneratedCode(\"Microsoft.Maui.Controls.SourceGen\", \"1.0.0.0\")]");
- sb.AppendLine($"\t\tpublic {rootType}(global::Microsoft.Maui.Controls.Xaml.XamlInflator inflator)");
+ sb.AppendLine($"\t\tinternal {rootType}(global::Microsoft.Maui.Controls.Xaml.XamlInflator inflator)");
sb.AppendLine("\t\t{");
sb.AppendLine("\t\t\tswitch (inflator)");
sb.AppendLine("\t\t\t{");
- if (xamlInflators == XamlInflator.Default || (xamlInflators & XamlInflator.Runtime) == XamlInflator.Runtime)
+ if ((xamlInflators & XamlInflator.Runtime) == XamlInflator.Runtime)
{
sb.AppendLine("\t\t\t\tcase global::Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime:");
sb.AppendLine("\t\t\t\t\tInitializeComponentRuntime();");
sb.AppendLine("\t\t\t\t\tbreak;");
}
- if (xamlInflators == XamlInflator.Default || (xamlInflators & XamlInflator.XamlC) == XamlInflator.XamlC)
+ if ((xamlInflators & XamlInflator.XamlC) == XamlInflator.XamlC)
{
sb.AppendLine("\t\t\t\tcase global::Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC:");
sb.AppendLine("\t\t\t\t\tInitializeComponentXamlC();");
sb.AppendLine("\t\t\t\t\tbreak;");
}
- if (xamlInflators == XamlInflator.Default || (xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen)
+ if ((xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen)
{
sb.AppendLine("\t\t\t\tcase global::Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen:");
sb.AppendLine("\t\t\t\t\tInitializeComponentSourceGen();");
sb.AppendLine("\t\t\t\t\tbreak;");
}
- sb.AppendLine("\t\t\t\tcase global::Microsoft.Maui.Controls.Xaml.XamlInflator.Default:");
- sb.AppendLine("\t\t\t\t\tInitializeComponent();");
- sb.AppendLine("\t\t\t\t\tbreak;");
sb.AppendLine("\t\t\t\tdefault:");
sb.AppendLine("\t\t\t\t\tthrow new global::System.NotSupportedException($\"no code for {inflator} generated. check the [XamlProcessing] attribute.\");");
sb.AppendLine("\t\t\t}");
@@ -301,12 +297,14 @@ public static bool TryParseXaml(XamlProjectItemForCB parseResult, string uid, Co
return false;
}
+#if _MAUIXAML_SOURCEGEN_BACKCOMPAT
// if the following xml processing instruction is present
//
//
//
// we will generate a xaml.g.cs file with the default ctor calling InitializeComponent, and a XamlCompilation attribute
var hasXamlCompilationProcessingInstruction = GetXamlCompilationProcessingInstruction(root.OwnerDocument);
+#endif
var rootClass = root.Attributes["Class", XamlParser.X2006Uri]
?? root.Attributes["Class", XamlParser.X2009Uri];
@@ -315,6 +313,7 @@ public static bool TryParseXaml(XamlProjectItemForCB parseResult, string uid, Co
{
XmlnsHelper.ParseXmlns(rootClass.Value, out rootType, out rootClrNamespace, out _, out _);
}
+#if _MAUIXAML_SOURCEGEN_BACKCOMPAT
else if (hasXamlCompilationProcessingInstruction && root.NamespaceURI == XamlParser.MauiUri)
{
rootClrNamespace = "__XamlGeneratedCode__";
@@ -323,6 +322,7 @@ public static bool TryParseXaml(XamlProjectItemForCB parseResult, string uid, Co
addXamlCompilationAttribute = true;
hideFromIntellisense = true;
}
+#endif
else if (parseResult?.ProjectItem?.ManifestResourceName != null && parseResult.ProjectItem.TargetPath != null)
{ // rootClass == null && !hasXamlCompilationProcessingInstruction) {
xamlResourceIdOnly = true; //only generate the XamlResourceId assembly attribute
@@ -345,6 +345,7 @@ public static bool TryParseXaml(XamlProjectItemForCB parseResult, string uid, Co
return true;
}
+#if _MAUIXAML_SOURCEGEN_BACKCOMPAT
//true, unless explicitely false
static bool GetXamlCompilationProcessingInstruction(XmlDocument xmlDoc)
{
@@ -358,6 +359,7 @@ static bool GetXamlCompilationProcessingInstruction(XmlDocument xmlDoc)
return true;
}
+#endif
internal static string GetWarningDisable(XmlDocument xmlDoc)
{
diff --git a/src/Controls/src/SourceGen/CodeBehindGenerator.cs b/src/Controls/src/SourceGen/CodeBehindGenerator.cs
index 3f67c36023b2..8bfc747f4005 100644
--- a/src/Controls/src/SourceGen/CodeBehindGenerator.cs
+++ b/src/Controls/src/SourceGen/CodeBehindGenerator.cs
@@ -218,26 +218,31 @@ static bool ShouldGenerateSourceGenInitializeComponent(XamlProjectItemForIC xaml
var rootClass = root.Attributes["Class", XamlParser.X2006Uri]
?? root.Attributes["Class", XamlParser.X2009Uri];
+ INamedTypeSymbol? rootType;
- if (rootClass == null)
- return false;
-
- XmlnsHelper.ParseXmlns(rootClass.Value, out var rootTypeName, out var rootClrNamespace, out _, out _);
+ if (rootClass != null)
+ {
+ XmlnsHelper.ParseXmlns(rootClass.Value, out var rootTypeName, out var rootClrNamespace, out _, out _);
+ rootType = compilation.GetTypeByMetadataName($"{rootClrNamespace}.{rootTypeName}");
+ }
+ else
+ { //no x:Class, but it can be an autogenerated type (starting with __Type, and with a XamlResourceId attribute)
+ ITypeSymbol xamlResIdAttr = compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Xaml.XamlResourceIdAttribute")!;
+ INamedTypeSymbol? GetTypeForResourcePath(string resourcePath, IAssemblySymbol assembly)
+ {
+ var attr = assembly.GetAttributes(xamlResIdAttr).FirstOrDefault(attr => (string)attr.ConstructorArguments[1].Value! == resourcePath);
+ return attr?.ConstructorArguments[2].Value as INamedTypeSymbol;
+ }
- var rootType = compilation.GetTypeByMetadataName($"{rootClrNamespace}.{rootTypeName}");
+ rootType = GetTypeForResourcePath(xamlItem.ProjectItem.RelativePath!, compilation.Assembly);
+ }
if (rootType == null)
return false;
- (_, var xamlInflators, var set) = rootType.GetXamlProcessing();
-
- //this test must go as soon as 'set' goes away
- if (!set)
- return false;
+ var xamlInflators = xamlItem.ProjectItem.Inflator;
- if ((xamlInflators & XamlInflator.SourceGen) != XamlInflator.SourceGen
- && xamlInflators != XamlInflator.Default
- && xamlItem.ProjectItem.ForceSourceGen == false)
+ if ((xamlInflators & XamlInflator.SourceGen) != XamlInflator.SourceGen)
return false;
return true;
diff --git a/src/Controls/src/SourceGen/GeneratorHelpers.cs b/src/Controls/src/SourceGen/GeneratorHelpers.cs
index ebf4360966a0..0be0f5e58b54 100644
--- a/src/Controls/src/SourceGen/GeneratorHelpers.cs
+++ b/src/Controls/src/SourceGen/GeneratorHelpers.cs
@@ -53,11 +53,33 @@ public static string EscapeIdentifier(string identifier)
fileOptions.TryGetValue("build_metadata.additionalfiles.ManifestResourceName", out var manifestResourceName);
fileOptions.TryGetValue("build_metadata.additionalfiles.RelativePath", out var relativePath);
fileOptions.TryGetValue("build_property.targetframework", out var targetFramework);
- fileOptions.TryGetValue("build_property._MauiForceXamlSourcegen", out var forceSourceGen);
fileOptions.TryGetValue("build_property.Configuration", out var configuration);
- return new ProjectItem(additionalText, targetPath: targetPath, relativePath: relativePath, manifestResourceName: manifestResourceName, kind: kind, targetFramework: targetFramework)
+
+ fileOptions.TryGetValue("build_metadata.additionalfiles.Inflator", out var inflator);
+
+
+ var xamlinflator = 0;
+ if (!string.IsNullOrEmpty(inflator))
+ {
+ var parts = inflator!.Split(',');
+ for (int i = 0; i < parts.Length; i++)
+ {
+ var trimmed = parts[i].Trim();
+ if (!Enum.TryParse(trimmed, true, out var xinfl))
+ throw new InvalidOperationException($"Invalid inflator '{trimmed}' for {additionalText.Path}.");
+ xamlinflator |= (int)xinfl;
+ }
+ }
+
+ return new ProjectItem
{
- ForceSourceGen = forceSourceGen == true.ToString(),
+ AdditionalText = additionalText,
+ TargetPath = targetPath,
+ RelativePath = relativePath,
+ ManifestResourceName = manifestResourceName,
+ Kind = kind,
+ Inflator = (XamlInflator)xamlinflator,
+ TargetFramework = targetFramework,
Configuration = configuration!,
};
}
diff --git a/src/Controls/src/SourceGen/ITypeSymbolExtensions.cs b/src/Controls/src/SourceGen/ITypeSymbolExtensions.cs
index 187f1069b96c..e1fa53e20815 100644
--- a/src/Controls/src/SourceGen/ITypeSymbolExtensions.cs
+++ b/src/Controls/src/SourceGen/ITypeSymbolExtensions.cs
@@ -167,38 +167,6 @@ public static bool ImplementsGeneric(this ITypeSymbol type, ITypeSymbol iface, o
return false;
}
- //FIXME: we won't need the set value in the future, but this allows to not generate for files without the attribute and avoid too many errors
- public static (bool generateInflatorSwitch, XamlInflator inflators, bool set) GetXamlProcessing(this ITypeSymbol type)
- {
- var attr = type.GetAttributes("Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute").FirstOrDefault(ad => ad.ConstructorArguments.Length >= 1);
- if (attr != null)
- {
- var inflator = (XamlInflator)attr.ConstructorArguments[0].Value!;
- var generateInflatorSwitch = attr.ConstructorArguments.Length == 2 && (bool)attr.ConstructorArguments[1].Value!;
- return (generateInflatorSwitch, inflator, true);
- }
-
- var module = type.ContainingModule;
- attr = module.GetAttributes("Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute").FirstOrDefault(ad => ad.ConstructorArguments.Length >= 1);
- if (attr != null)
- {
- var inflator = (XamlInflator)attr.ConstructorArguments[0].Value!;
- var generateInflatorSwitch = attr.ConstructorArguments.Length == 2 && (bool)attr.ConstructorArguments[1].Value!;
- return (generateInflatorSwitch, inflator, true);
- }
-
- var assembly = type.ContainingAssembly;
- attr = assembly.GetAttributes("Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute").FirstOrDefault(ad => ad.ConstructorArguments.Length >= 1);
- if (attr != null)
- {
- var inflator = (XamlInflator)attr.ConstructorArguments[0].Value!;
- var generateInflatorSwitch = attr.ConstructorArguments.Length == 2 && (bool)attr.ConstructorArguments[1].Value!;
- return (generateInflatorSwitch, inflator, true);
- }
-
- return (false, XamlInflator.Default, false);
- }
-
public static bool IsPublic(this ISymbol symbol)
=> symbol.DeclaredAccessibility == Accessibility.Public;
public static bool IsPublicOrVisibleInternal(this ITypeSymbol type, IEnumerable internalsVisible)
diff --git a/src/Controls/src/SourceGen/InitializeComponentCodeWriter.cs b/src/Controls/src/SourceGen/InitializeComponentCodeWriter.cs
index 2026ecffb121..ded9035cf1d6 100644
--- a/src/Controls/src/SourceGen/InitializeComponentCodeWriter.cs
+++ b/src/Controls/src/SourceGen/InitializeComponentCodeWriter.cs
@@ -6,6 +6,7 @@
using System.Runtime.InteropServices;
using System.Xml;
using Microsoft.CodeAnalysis;
+using System.Linq;
using Microsoft.Maui.Controls.Xaml;
namespace Microsoft.Maui.Controls.SourceGen;
@@ -45,9 +46,11 @@ PrePost newblock() =>
}
var root = xamlItem.Root!;
+ string accessModifier = "public";
+ INamedTypeSymbol? rootType = null;
+
if (root.Properties.TryGetValue(XmlName.xClass, out var classNode))
{
- string accessModifier = "public";
if ((classNode as ValueNode)?.Value is not string rootClass)
goto exit;
@@ -56,58 +59,61 @@ PrePost newblock() =>
var classModifier = (classModifierNode as ValueNode)?.Value as string;
accessModifier = classModifier?.ToLowerInvariant().Replace("notpublic", "internal") ?? "public"; // notpublic is WPF for internal
}
-
//TODO support x:TypeArguments
XmlnsHelper.ParseXmlns(rootClass, out var rootTypeName, out var rootClrNamespace, out _, out _);
- var rootType = compilation.GetTypeByMetadataName($"{rootClrNamespace}.{rootTypeName}");
- //roottype null might mean we need to add the type to the Compilation, we'll figure that out later
- if (rootType == null)
- goto exit;
+ rootType = compilation.GetTypeByMetadataName($"{rootClrNamespace}.{rootTypeName}");
+ }
+ else
+ { //no x:Class, but it can be an autogenerated type (starting with __Type, and with a XamlResourceId attribute)
+ ITypeSymbol xamlResIdAttr = compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Xaml.XamlResourceIdAttribute")!;
+ INamedTypeSymbol? GetTypeForResourcePath(string resourcePath, IAssemblySymbol assembly)
+ {
+ var attr = assembly.GetAttributes(xamlResIdAttr).FirstOrDefault(attr => (string)attr.ConstructorArguments[1].Value! == resourcePath);
+ return attr?.ConstructorArguments[2].Value as INamedTypeSymbol;
+ }
- (var genSwitch, var xamlInflators, var set) = rootType.GetXamlProcessing();
+ rootType = GetTypeForResourcePath(xamlItem.ProjectItem.RelativePath!, compilation.Assembly);
+ }
- //FIXME later we shouln't gnerate the file at all if generate is false
- var generate = (xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen
- || xamlItem.ProjectItem.ForceSourceGen
- || xamlInflators == XamlInflator.Default && genSwitch;
+ if (rootType == null)
+ goto exit;
- if (!generate)
- goto exit;
+ var genSwitch = compilation.AssemblyName == "Microsoft.Maui.Controls.Xaml.UnitTests";
+ var xamlInflators = xamlItem.ProjectItem.Inflator;
- codeWriter.WriteLine($"namespace {rootClrNamespace};");
- codeWriter.WriteLine();
+ var generate = (xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen;
+
+ if (!generate)
+ goto exit;
+
+ codeWriter.WriteLine($"namespace {rootType.ContainingNamespace};");
+ codeWriter.WriteLine();
+ if (!rootType.Name.StartsWith("__Type"))
codeWriter.WriteLine(GeneratedCodeAttribute);
- codeWriter.WriteLine($"{accessModifier} partial class {rootTypeName}");
+ codeWriter.WriteLine($"{accessModifier} partial class {rootType.Name}");
+ using (newblock())
+ {
+ var methodName = genSwitch ? "InitializeComponentSourceGen" : "InitializeComponent";
+ codeWriter.WriteLine($"private partial void {methodName}()");
+ xamlItem.Root!.XmlType.TryResolveTypeSymbol(null, compilation, xmlnsCache, out var baseType);
+ var sgcontext = new SourceGenContext(codeWriter, compilation, sourceProductionContext, xmlnsCache, typeCache, rootType!, baseType) { FilePath = xamlItem.ProjectItem.RelativePath };
using (newblock())
{
- var methodName = genSwitch ? "InitializeComponentSourceGen" : "InitializeComponent";
- codeWriter.WriteLine($"private partial void {methodName}()");
- xamlItem.Root!.XmlType.TryResolveTypeSymbol(null, compilation, xmlnsCache, out var baseType);
- var sgcontext = new SourceGenContext(codeWriter, compilation, sourceProductionContext, xmlnsCache, typeCache, rootType!, baseType) { FilePath = xamlItem.ProjectItem.RelativePath };
- using (newblock())
- {
- Visit(root, sgcontext);
-
- foreach (var localMethod in sgcontext.LocalMethods)
- {
- codeWriter.WriteLine(localMethod);
- codeWriter.WriteLine();
- }
- }
+ Visit(root, sgcontext);
- foreach (var writer in sgcontext.AddtitionalWriters)
+ foreach (var localMethod in sgcontext.LocalMethods)
{
- codeWriter.Write(writer.ToString());
+ codeWriter.WriteLine(localMethod);
codeWriter.WriteLine();
}
}
- }
- else
- { //No x:Class attribute
- //TODO
-
+ foreach (var writer in sgcontext.AddtitionalWriters)
+ {
+ codeWriter.Write(writer.ToString());
+ codeWriter.WriteLine();
+ }
}
exit:
codeWriter.Flush();
diff --git a/src/Controls/src/SourceGen/ProjectItem.cs b/src/Controls/src/SourceGen/ProjectItem.cs
index 896ed1185cf6..7a3200c7f063 100644
--- a/src/Controls/src/SourceGen/ProjectItem.cs
+++ b/src/Controls/src/SourceGen/ProjectItem.cs
@@ -1,27 +1,19 @@
using Microsoft.CodeAnalysis;
+using Microsoft.Maui.Controls.Xaml;
namespace Microsoft.Maui.Controls.SourceGen;
-class ProjectItem
+record ProjectItem
{
- public ProjectItem(AdditionalText additionalText, string? targetPath, string? relativePath, string? manifestResourceName, string kind, string? targetFramework)
- {
- AdditionalText = additionalText;
- TargetPath = targetPath ?? additionalText.Path;
- RelativePath = relativePath;
- ManifestResourceName = manifestResourceName;
- Kind = kind;
- TargetFramework = targetFramework;
- }
-
- public AdditionalText AdditionalText { get; }
- public string? TargetPath { get; }
- public string? RelativePath { get; }
- public string? ManifestResourceName { get; }
- public string Kind { get; }
- public string? TargetFramework { get; }
+ public required AdditionalText AdditionalText { get; init; }
+ private string? _targetPath;
+ public string? TargetPath { get => _targetPath ?? AdditionalText.Path; init => _targetPath = value; }
+ public string? RelativePath { get; init; }
+ public string? ManifestResourceName { get; init; }
+ public required string Kind { get; init; }
+ public string? TargetFramework { get; init; }
+ public required XamlInflator Inflator { get; init; }
//bypass attribute check. used for testing
- public bool ForceSourceGen { get; internal set; }
public string Configuration { get; internal set; } = "Debug";
}
diff --git a/src/Controls/src/SourceGen/compat.cs b/src/Controls/src/SourceGen/compat.cs
new file mode 100644
index 000000000000..49832e9e3e1c
--- /dev/null
+++ b/src/Controls/src/SourceGen/compat.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//allow usage of required and record in netstandard2.0
+
+using System.ComponentModel;
+
+namespace System.Runtime.CompilerServices
+{
+#if !NET5_0_OR_GREATER
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ internal static class IsExternalInit {}
+
+#endif // !NET5_0_OR_GREATER
+
+#if !NET7_0_OR_GREATER
+
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
+ internal sealed class RequiredMemberAttribute : Attribute {}
+
+ [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
+ internal sealed class CompilerFeatureRequiredAttribute : Attribute
+ {
+ public CompilerFeatureRequiredAttribute(string featureName)
+ {
+ FeatureName = featureName;
+ }
+
+ public string FeatureName { get; }
+ public bool IsOptional { get; init; }
+
+ public const string RefStructs = nameof(RefStructs);
+ public const string RequiredMembers = nameof(RequiredMembers);
+ }
+
+#endif // !NET7_0_OR_GREATER
+}
+
+namespace System.Diagnostics.CodeAnalysis
+{
+#if !NET7_0_OR_GREATER
+ [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
+ internal sealed class SetsRequiredMembersAttribute : Attribute {}
+#endif
+}
\ No newline at end of file
diff --git a/src/Controls/src/Xaml/PublicAPI/net-android/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-android/PublicAPI.Unshipped.txt
index c35016ca9941..e393e24d2252 100644
--- a/src/Controls/src/Xaml/PublicAPI/net-android/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Xaml/PublicAPI/net-android/PublicAPI.Unshipped.txt
@@ -8,14 +8,6 @@
*REMOVED*~Microsoft.Maui.Controls.Xaml.FontImageExtension.ProvideValue(System.IServiceProvider serviceProvider) -> Microsoft.Maui.Controls.ImageSource
*REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.get -> double
*REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.set -> void
-Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator
Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider
~Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(string dataType) -> void
~Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(object rootObject) -> void
diff --git a/src/Controls/src/Xaml/PublicAPI/net-ios/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-ios/PublicAPI.Unshipped.txt
index c35016ca9941..e393e24d2252 100644
--- a/src/Controls/src/Xaml/PublicAPI/net-ios/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Xaml/PublicAPI/net-ios/PublicAPI.Unshipped.txt
@@ -8,14 +8,6 @@
*REMOVED*~Microsoft.Maui.Controls.Xaml.FontImageExtension.ProvideValue(System.IServiceProvider serviceProvider) -> Microsoft.Maui.Controls.ImageSource
*REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.get -> double
*REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.set -> void
-Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator
Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider
~Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(string dataType) -> void
~Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(object rootObject) -> void
diff --git a/src/Controls/src/Xaml/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
index c35016ca9941..e393e24d2252 100644
--- a/src/Controls/src/Xaml/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Xaml/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
@@ -8,14 +8,6 @@
*REMOVED*~Microsoft.Maui.Controls.Xaml.FontImageExtension.ProvideValue(System.IServiceProvider serviceProvider) -> Microsoft.Maui.Controls.ImageSource
*REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.get -> double
*REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.set -> void
-Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator
Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider
~Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(string dataType) -> void
~Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(object rootObject) -> void
diff --git a/src/Controls/src/Xaml/PublicAPI/net-tizen/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
index c35016ca9941..e393e24d2252 100644
--- a/src/Controls/src/Xaml/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Xaml/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
@@ -8,14 +8,6 @@
*REMOVED*~Microsoft.Maui.Controls.Xaml.FontImageExtension.ProvideValue(System.IServiceProvider serviceProvider) -> Microsoft.Maui.Controls.ImageSource
*REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.get -> double
*REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.set -> void
-Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator
Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider
~Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(string dataType) -> void
~Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(object rootObject) -> void
diff --git a/src/Controls/src/Xaml/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-windows/PublicAPI.Unshipped.txt
index 1393cf62e369..8c0c1145a575 100644
--- a/src/Controls/src/Xaml/PublicAPI/net-windows/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Xaml/PublicAPI/net-windows/PublicAPI.Unshipped.txt
@@ -68,14 +68,6 @@ Microsoft.Maui.Controls.Xaml.XamlCompilationOptions
Microsoft.Maui.Controls.Xaml.XamlCompilationOptions.Compile = 2 -> Microsoft.Maui.Controls.Xaml.XamlCompilationOptions
Microsoft.Maui.Controls.Xaml.XamlCompilationOptions.Skip = 1 -> Microsoft.Maui.Controls.Xaml.XamlCompilationOptions
Microsoft.Maui.Controls.Xaml.XamlFilePathAttribute
-Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator
Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider
~Microsoft.Maui.Controls.Xaml.AppThemeBindingExtension.Dark.get -> object
~Microsoft.Maui.Controls.Xaml.AppThemeBindingExtension.Dark.set -> void
diff --git a/src/Controls/src/Xaml/PublicAPI/net/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net/PublicAPI.Unshipped.txt
index c35016ca9941..e393e24d2252 100644
--- a/src/Controls/src/Xaml/PublicAPI/net/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Xaml/PublicAPI/net/PublicAPI.Unshipped.txt
@@ -8,14 +8,6 @@
*REMOVED*~Microsoft.Maui.Controls.Xaml.FontImageExtension.ProvideValue(System.IServiceProvider serviceProvider) -> Microsoft.Maui.Controls.ImageSource
*REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.get -> double
*REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.set -> void
-Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator
Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider
~Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(string dataType) -> void
~Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(object rootObject) -> void
diff --git a/src/Controls/src/Xaml/PublicAPI/netstandard/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/netstandard/PublicAPI.Unshipped.txt
index c35016ca9941..e393e24d2252 100644
--- a/src/Controls/src/Xaml/PublicAPI/netstandard/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Xaml/PublicAPI/netstandard/PublicAPI.Unshipped.txt
@@ -8,14 +8,6 @@
*REMOVED*~Microsoft.Maui.Controls.Xaml.FontImageExtension.ProvideValue(System.IServiceProvider serviceProvider) -> Microsoft.Maui.Controls.ImageSource
*REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.get -> double
*REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.set -> void
-Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void
-Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator
Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider
~Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(string dataType) -> void
~Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(object rootObject) -> void
diff --git a/src/Controls/src/Xaml/XamlCompilationAttribute.cs b/src/Controls/src/Xaml/XamlCompilationAttribute.cs
index e0e923ebecc8..6bfec7586c52 100644
--- a/src/Controls/src/Xaml/XamlCompilationAttribute.cs
+++ b/src/Controls/src/Xaml/XamlCompilationAttribute.cs
@@ -4,8 +4,9 @@
namespace Microsoft.Maui.Controls.Xaml
{
- // TODO: obsolete when we are ready to switch to SourceGen
- // [Obsolete("use XamlProcessingOptions instead.")]
+#if !_MAUIXAML_SOURCEGEN_BACKCOMPAT
+ [Obsolete("Specify xaml inflator and other options using msbuild metadata on MauiXaml items in your .csproj: ", error: true)]
+#endif
[Flags]
public enum XamlCompilationOptions
{
@@ -13,8 +14,9 @@ public enum XamlCompilationOptions
Compile = XamlInflator.XamlC,
}
- // TODO: obsolete when we are ready to switch to SourceGen
- // [Obsolete("use XamlProcessingAttribute instead.")]
+#if !_MAUIXAML_SOURCEGEN_BACKCOMPAT
+ [Obsolete("Specify xaml inflator and other options using msbuild metadata on MauiXaml items in your .csproj: ", error: true)]
+#endif
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class, Inherited = false)]
public sealed class XamlCompilationAttribute : Attribute
{
@@ -26,11 +28,11 @@ public XamlCompilationAttribute(XamlCompilationOptions xamlCompilationOptions)
public XamlCompilationOptions XamlCompilationOptions { get; set; }
}
+#if _MAUIXAML_SOURCEGEN_BACKCOMPAT
static class XamlCExtensions
{
public static bool IsCompiled(this Type type)
{
-#pragma warning disable CS0618 // Type or member is obsolete
var attr = type.GetCustomAttribute();
if (attr != null)
return attr.XamlCompilationOptions == XamlCompilationOptions.Compile;
@@ -42,7 +44,7 @@ public static bool IsCompiled(this Type type)
return attr.XamlCompilationOptions == XamlCompilationOptions.Compile;
return false;
-#pragma warning restore CS0618 // Type or member is obsolete
}
}
+#endif
}
\ No newline at end of file
diff --git a/src/Controls/src/Xaml/XamlInflator.cs b/src/Controls/src/Xaml/XamlInflator.cs
index b5746ba79124..dc2a4a59c436 100644
--- a/src/Controls/src/Xaml/XamlInflator.cs
+++ b/src/Controls/src/Xaml/XamlInflator.cs
@@ -1,16 +1,9 @@
-namespace Microsoft.Maui.Controls.Xaml
+namespace Microsoft.Maui.Controls.Xaml;
+
+//used for unit testing switching, and internal use of the sourcegen
+enum XamlInflator
{
- public enum XamlInflator
- {
- ///
- /// Picks the best Inflator available, don't change it unless you know what you're doing.
- ///
- Default = 0,
- Runtime = 1 << 0,
- XamlC = 1 << 1,
-#if !NETSTANDARD2_0 && !NETSTANDARD2_1
- [System.Runtime.Versioning.RequiresPreviewFeatures]
-#endif
- SourceGen = 1 << 2,
- }
+ Runtime = 1 << 0,
+ XamlC = 1 << 1,
+ SourceGen = 1 << 2,
}
\ No newline at end of file
diff --git a/src/Controls/src/Xaml/XamlProcessingAttribute.cs b/src/Controls/src/Xaml/XamlProcessingAttribute.cs
deleted file mode 100644
index a694dc9f816f..000000000000
--- a/src/Controls/src/Xaml/XamlProcessingAttribute.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Runtime.Versioning;
-
-namespace Microsoft.Maui.Controls.Xaml;
-
-[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class, Inherited = false)]
-//when we remove this attribute, we'll have to obsolete XamlCompilationAttribute
-#if !NETSTANDARD
-[System.Runtime.Versioning.RequiresPreviewFeatures]
-#endif
-public sealed class XamlProcessingAttribute : Attribute
-{
- public XamlProcessingAttribute(XamlInflator inflator)
- {
- if ((inflator & (inflator - 1)) != 0) //check if only one bit is set (http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
- throw new ArgumentException("Only one option can be set at a time");
- XamlInflator = inflator;
- }
-
- internal XamlProcessingAttribute(XamlInflator inflators, bool generateInflatorSwitch)
- {
- XamlInflator = inflators; //used as a flag to indicate the infators used for unit test purposes
- GenerateInflatorSwitch = generateInflatorSwitch;
- }
-
- public XamlInflator XamlInflator { get; }
- internal bool GenerateInflatorSwitch { get; }
-}
\ No newline at end of file
diff --git a/src/Controls/tests/SourceGen.UnitTests/SourceGeneratorDriver.cs b/src/Controls/tests/SourceGen.UnitTests/SourceGeneratorDriver.cs
index 0d0833fa058d..0f58065a9d3c 100644
--- a/src/Controls/tests/SourceGen.UnitTests/SourceGeneratorDriver.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/SourceGeneratorDriver.cs
@@ -151,6 +151,7 @@ public override bool TryGetValue(string key, [NotNullWhen(true)] out string? val
"build_metadata.additionalfiles.TargetPath" => _additionalFile.TargetPath,
"build_metadata.additionalfiles.ManifestResourceName" => _additionalFile.ManifestResourceName,
"build_metadata.additionalfiles.RelativePath" => _additionalFile.RelativePath,
+ "build_metadata.additionalfiles.Inflator" => "SourceGen",
"build_property.targetframework" => _additionalFile.TargetFramework,
_ => null
};
diff --git a/src/Controls/tests/TestCases.HostApp/Elements/CollectionView/HeaderFooterGalleries/HeaderFooterView.xaml b/src/Controls/tests/TestCases.HostApp/Elements/CollectionView/HeaderFooterGalleries/HeaderFooterView.xaml
index f1a9f5af30e3..0bda91b2ddd1 100644
--- a/src/Controls/tests/TestCases.HostApp/Elements/CollectionView/HeaderFooterGalleries/HeaderFooterView.xaml
+++ b/src/Controls/tests/TestCases.HostApp/Elements/CollectionView/HeaderFooterGalleries/HeaderFooterView.xaml
@@ -1,4 +1,4 @@
-
+
false
0114;0672;0108;0067;0168;0169;0219;0612;0618;1998
Controls.Xaml.UnitTests.ExternalAssembly
+
+
@@ -21,6 +24,7 @@
+
diff --git a/src/Controls/tests/Xaml.UnitTests/AcceptEmptyServiceProvider.xaml.cs b/src/Controls/tests/Xaml.UnitTests/AcceptEmptyServiceProvider.xaml.cs
index eeeb46884c9a..f3cfea50a960 100644
--- a/src/Controls/tests/Xaml.UnitTests/AcceptEmptyServiceProvider.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/AcceptEmptyServiceProvider.xaml.cs
@@ -20,7 +20,6 @@ object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
}
}
- [XamlProcessing(XamlInflator.Default, true)]
public partial class AcceptEmptyServiceProvider : ContentPage
{
public AcceptEmptyServiceProvider()
diff --git a/src/Controls/tests/Xaml.UnitTests/AppResources/Colors.xaml b/src/Controls/tests/Xaml.UnitTests/AppResources/Colors.rtxc.xaml
similarity index 100%
rename from src/Controls/tests/Xaml.UnitTests/AppResources/Colors.xaml
rename to src/Controls/tests/Xaml.UnitTests/AppResources/Colors.rtxc.xaml
diff --git a/src/Controls/tests/Xaml.UnitTests/AppResources/CompiledColors.xaml b/src/Controls/tests/Xaml.UnitTests/AppResources/CompiledColors.rtxc.xaml
similarity index 100%
rename from src/Controls/tests/Xaml.UnitTests/AppResources/CompiledColors.xaml
rename to src/Controls/tests/Xaml.UnitTests/AppResources/CompiledColors.rtxc.xaml
diff --git a/src/Controls/tests/Xaml.UnitTests/AppResources/RD13209.xaml b/src/Controls/tests/Xaml.UnitTests/AppResources/RD13209.rtxc.xaml
similarity index 100%
rename from src/Controls/tests/Xaml.UnitTests/AppResources/RD13209.xaml
rename to src/Controls/tests/Xaml.UnitTests/AppResources/RD13209.rtxc.xaml
diff --git a/src/Controls/tests/Xaml.UnitTests/AutoMergedResourceDictionaries.xaml b/src/Controls/tests/Xaml.UnitTests/AutoMergedResourceDictionaries.xaml
index e47fdb970c53..ce9d29db2111 100644
--- a/src/Controls/tests/Xaml.UnitTests/AutoMergedResourceDictionaries.xaml
+++ b/src/Controls/tests/Xaml.UnitTests/AutoMergedResourceDictionaries.xaml
@@ -7,7 +7,7 @@
Purple
Pink
-
+
diff --git a/src/Controls/tests/Xaml.UnitTests/AutoMergedResourceDictionaries.xaml.cs b/src/Controls/tests/Xaml.UnitTests/AutoMergedResourceDictionaries.xaml.cs
index a052f567bbdf..40a5c20c1fbf 100644
--- a/src/Controls/tests/Xaml.UnitTests/AutoMergedResourceDictionaries.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/AutoMergedResourceDictionaries.xaml.cs
@@ -5,7 +5,6 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class AutoMergedResourceDictionaries : ContentPage
{
public AutoMergedResourceDictionaries()
@@ -14,7 +13,7 @@ public AutoMergedResourceDictionaries()
}
[TestFixture]
- public class Tests
+ class Tests
{
[SetUp] public void Setup() => Application.Current = new MockApplication();
[TearDown] public void TearDown() => Application.Current = null;
diff --git a/src/Controls/tests/Xaml.UnitTests/AutomationProperties.xaml.cs b/src/Controls/tests/Xaml.UnitTests/AutomationProperties.xaml.cs
index 510d97d16c8d..ab7057ecce5e 100644
--- a/src/Controls/tests/Xaml.UnitTests/AutomationProperties.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/AutomationProperties.xaml.cs
@@ -1,18 +1,13 @@
-using System;
-using System.Reflection;
using Microsoft.Maui.Controls.Core.UnitTests;
-using Microsoft.Maui.Controls.Xaml;
using NUnit.Framework;
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-
-[XamlProcessing(XamlInflator.Default, true)]
-public partial class AutomationProperties : ContentPage
+partial class AutomationProperties : ContentPage
{
public AutomationProperties() => InitializeComponent();
[TestFixture]
- public class Tests
+ class Tests
{
[SetUp] public void Setup() => Application.Current = new MockApplication();
[TearDown] public void TearDown() => Application.Current = null;
diff --git a/src/Controls/tests/Xaml.UnitTests/BindablePropertiesAccessModifiers.xaml.cs b/src/Controls/tests/Xaml.UnitTests/BindablePropertiesAccessModifiers.xaml.cs
index 90ba95f7b24a..df69b3653ef0 100644
--- a/src/Controls/tests/Xaml.UnitTests/BindablePropertiesAccessModifiers.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/BindablePropertiesAccessModifiers.xaml.cs
@@ -34,15 +34,13 @@ public class BindablePropertiesAccessModifiersVM
public string Bar => "Bar";
}
-
-[XamlProcessing(XamlInflator.Default, true)]
public partial class BindablePropertiesAccessModifiers : ContentPage
{
public BindablePropertiesAccessModifiers() => InitializeComponent();
[TestFixture]
- public class Tests
+ class Tests
{
[SetUp] public void Setup() => Application.Current = new MockApplication();
[TearDown] public void TearDown() => Application.Current = null;
diff --git a/src/Controls/tests/Xaml.UnitTests/BindingDiagnosticsTests.xaml b/src/Controls/tests/Xaml.UnitTests/BindingDiagnosticsTests.rt.xaml
similarity index 100%
rename from src/Controls/tests/Xaml.UnitTests/BindingDiagnosticsTests.xaml
rename to src/Controls/tests/Xaml.UnitTests/BindingDiagnosticsTests.rt.xaml
diff --git a/src/Controls/tests/Xaml.UnitTests/BindingDiagnosticsTests.xaml.cs b/src/Controls/tests/Xaml.UnitTests/BindingDiagnosticsTests.rt.xaml.cs
similarity index 95%
rename from src/Controls/tests/Xaml.UnitTests/BindingDiagnosticsTests.xaml.cs
rename to src/Controls/tests/Xaml.UnitTests/BindingDiagnosticsTests.rt.xaml.cs
index 9903feaf6e4d..841edd92e483 100644
--- a/src/Controls/tests/Xaml.UnitTests/BindingDiagnosticsTests.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/BindingDiagnosticsTests.rt.xaml.cs
@@ -6,7 +6,6 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Runtime, true)]
public partial class BindingDiagnosticsTests : ContentPage
{
public BindingDiagnosticsTests() => InitializeComponent();
@@ -15,7 +14,7 @@ public partial class BindingDiagnosticsTests : ContentPage
#if !DEBUG
[Ignore("This test runs only in debug")]
#endif
- public class Tests
+ class Tests
{
bool enableDiagnosticsInitialState;
diff --git a/src/Controls/tests/Xaml.UnitTests/BindingsCompiler.xaml.cs b/src/Controls/tests/Xaml.UnitTests/BindingsCompiler.xaml.cs
index f2addf96c308..774d21532b96 100644
--- a/src/Controls/tests/Xaml.UnitTests/BindingsCompiler.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/BindingsCompiler.xaml.cs
@@ -10,7 +10,6 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests
{
- [XamlProcessing(XamlInflator.Default, true)]
public partial class BindingsCompiler : ContentPage
{
public BindingsCompiler()
@@ -19,7 +18,7 @@ public BindingsCompiler()
}
[TestFixture]
- public class Tests
+ class Tests
{
[SetUp] public void Setup() => DispatcherProvider.SetCurrent(new DispatcherProviderStub());
[TearDown] public void TearDown() => DispatcherProvider.SetCurrent(null);
@@ -27,9 +26,6 @@ public class Tests
[Test]
public void Test([Values] XamlInflator inflator)
{
- if (inflator == XamlInflator.Default)
- Assert.Ignore("not testing for default");
-
var vm = new MockViewModel
{
Text = "Text0",
diff --git a/src/Controls/tests/Xaml.UnitTests/Border.xaml.cs b/src/Controls/tests/Xaml.UnitTests/Border.xaml.cs
index bb23173e5f41..5ec438ee52f5 100644
--- a/src/Controls/tests/Xaml.UnitTests/Border.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/Border.xaml.cs
@@ -7,13 +7,12 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class Border : ContentPage
{
public Border() => InitializeComponent();
[TestFixture]
- public class Tests
+ class Tests
{
[Test]
public void InitializeStrokeShape([Values] XamlInflator inflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/BuiltInConversions.xaml.cs b/src/Controls/tests/Xaml.UnitTests/BuiltInConversions.xaml.cs
index e6a956be02ae..b89a645aa84c 100644
--- a/src/Controls/tests/Xaml.UnitTests/BuiltInConversions.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/BuiltInConversions.xaml.cs
@@ -4,13 +4,12 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class BuiltInConversions : ContentPage
{
public BuiltInConversions() => InitializeComponent();
[TestFixture]
- public class Tests
+ class Tests
{
[SetUp] public void Setup() => Application.Current = new MockApplication();
[TearDown] public void TearDown() => Application.Current = null;
diff --git a/src/Controls/tests/Xaml.UnitTests/ButtonCornerRadius.xaml.cs b/src/Controls/tests/Xaml.UnitTests/ButtonCornerRadius.xaml.cs
index 967d0e56ab4c..c5ce3fb9262a 100644
--- a/src/Controls/tests/Xaml.UnitTests/ButtonCornerRadius.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/ButtonCornerRadius.xaml.cs
@@ -3,13 +3,12 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class ButtonCornerRadius : ContentPage
{
public ButtonCornerRadius() => InitializeComponent();
[TestFixture]
- public class Tests
+ class Tests
{
[SetUp] public void Setup() => Application.Current = new MockApplication();
[TearDown] public void TearDown() => Application.Current = null;
diff --git a/src/Controls/tests/Xaml.UnitTests/CecilExtensionsTests.cs b/src/Controls/tests/Xaml.UnitTests/CecilExtensionsTests.cs
index d3fa710e3834..6a6d05de3ecb 100644
--- a/src/Controls/tests/Xaml.UnitTests/CecilExtensionsTests.cs
+++ b/src/Controls/tests/Xaml.UnitTests/CecilExtensionsTests.cs
@@ -72,7 +72,7 @@ EmbeddedResource GetResource(string name)
// "IsCompiledDefault",
"X2006Namespace",
"X2009Primitives",
- "Validation.MissingXClass",
+ "Validation.MissingXClass.rtxc",
};
[Test, TestCaseSource(nameof(IsXamlTrueSource))]
diff --git a/src/Controls/tests/Xaml.UnitTests/ColorConverter.xaml.cs b/src/Controls/tests/Xaml.UnitTests/ColorConverter.xaml.cs
index faa040060621..cadb0685ef67 100644
--- a/src/Controls/tests/Xaml.UnitTests/ColorConverter.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/ColorConverter.xaml.cs
@@ -8,14 +8,13 @@ public class ColorConverterVM
public string ButtonBackground => "#fc87ad";
}
-[XamlProcessing(XamlInflator.Default, true)]
public partial class ColorConverter : ContentPage
{
public ColorConverter() => InitializeComponent();
[TestFixture]
- public class Tests
+ class Tests
{
[Test]
public void StringsAreValidAsColor([Values] XamlInflator inflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/CompiledTypeConverter.xaml.cs b/src/Controls/tests/Xaml.UnitTests/CompiledTypeConverter.xaml.cs
index e255ef5dd6c1..3f182224e74a 100644
--- a/src/Controls/tests/Xaml.UnitTests/CompiledTypeConverter.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/CompiledTypeConverter.xaml.cs
@@ -11,7 +11,6 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class CompiledTypeConverter : ContentPage
{
public static readonly BindableProperty RectangleBPProperty =
@@ -71,7 +70,7 @@ public Rect RectangleBP
public CompiledTypeConverter() => InitializeComponent();
[TestFixture]
- public class Tests
+ class Tests
{
[Test]
public void CompiledTypeConverterAreInvoked([Values] XamlInflator xamlInflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/ConstraintExpression.xaml.cs b/src/Controls/tests/Xaml.UnitTests/ConstraintExpression.xaml.cs
index def35c3e903b..87d0e2dc4e4e 100644
--- a/src/Controls/tests/Xaml.UnitTests/ConstraintExpression.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/ConstraintExpression.xaml.cs
@@ -6,13 +6,12 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class ConstraintExpression : ContentPage
{
public ConstraintExpression() => InitializeComponent();
[TestFixture]
- public class Tests
+ class Tests
{
[Test]
public void ConstantConstraint([Values] XamlInflator inflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj b/src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj
index ab1747f3dc04..768bc0cdee89 100644
--- a/src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj
+++ b/src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj
@@ -10,13 +10,13 @@
false
true
true
- $(DefineConstants);MauiAllowImplicitXmlnsDeclaration;_MAUIXAML_SG_SOURCEINFO;_MAUIXAML_SG_NULLABLE_ENABLE
+ $(DefineConstants);MauiAllowImplicitXmlnsDeclaration
+ $(DefineConstants);_MAUIXAML_SG_SOURCEINFO;_MAUIXAML_SG_NULLABLE_ENABLE
-
$(DefineConstants);FIXME_BEFORE_PUBLIC_RELEASE
-
+
true
Generated
True
@@ -66,11 +66,19 @@
+
+
-
-
-
+
+
-
+
+
+
+
+
+
+
+
diff --git a/src/Controls/tests/Xaml.UnitTests/CustomButtonNoBaseClass.xaml.cs b/src/Controls/tests/Xaml.UnitTests/CustomButtonNoBaseClass.xaml.cs
index 9e19818564cd..f0f8f5da6a72 100644
--- a/src/Controls/tests/Xaml.UnitTests/CustomButtonNoBaseClass.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/CustomButtonNoBaseClass.xaml.cs
@@ -1,6 +1,5 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class CustomButtonNoBaseClass //DO NOT add base class here
{
public CustomButtonNoBaseClass()
diff --git a/src/Controls/tests/Xaml.UnitTests/CustomXamlView.xaml.cs b/src/Controls/tests/Xaml.UnitTests/CustomXamlView.xaml.cs
index 6dac905120bf..cdf4ab078204 100644
--- a/src/Controls/tests/Xaml.UnitTests/CustomXamlView.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/CustomXamlView.xaml.cs
@@ -1,7 +1,5 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
-
public partial class CustomXamlView : ContentView
{
public CustomXamlView() => InitializeComponent();
diff --git a/src/Controls/tests/Xaml.UnitTests/DataTemplate.xaml.cs b/src/Controls/tests/Xaml.UnitTests/DataTemplate.xaml.cs
index 3697bdcb9190..e1ad13113003 100644
--- a/src/Controls/tests/Xaml.UnitTests/DataTemplate.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/DataTemplate.xaml.cs
@@ -4,7 +4,6 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests
{
- [XamlProcessing(XamlInflator.Default, true)]
public partial class DataTemplate : ContentPage
{
public DataTemplate()
@@ -13,7 +12,7 @@ public DataTemplate()
}
[TestFixture]
- public class Tests
+ class Tests
{
[SetUp] public void Setup() => DispatcherProvider.SetCurrent(new DispatcherProviderStub());
[TearDown] public void TearDown() => DispatcherProvider.SetCurrent(null);
diff --git a/src/Controls/tests/Xaml.UnitTests/DataTemplateExtension.xaml.cs b/src/Controls/tests/Xaml.UnitTests/DataTemplateExtension.xaml.cs
index a0a7933514cd..0817305fe28a 100644
--- a/src/Controls/tests/Xaml.UnitTests/DataTemplateExtension.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/DataTemplateExtension.xaml.cs
@@ -2,7 +2,6 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class DataTemplateExtension : ContentPage
{
public DataTemplateExtension() => InitializeComponent();
diff --git a/src/Controls/tests/Xaml.UnitTests/DefinitionCollectionTests.xaml.cs b/src/Controls/tests/Xaml.UnitTests/DefinitionCollectionTests.xaml.cs
index 53a48213d4f7..d361c4ce0246 100644
--- a/src/Controls/tests/Xaml.UnitTests/DefinitionCollectionTests.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/DefinitionCollectionTests.xaml.cs
@@ -11,7 +11,6 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class DefinitionCollectionTests : ContentPage
{
public DefinitionCollectionTests() => InitializeComponent();
diff --git a/src/Controls/tests/Xaml.UnitTests/DuplicatePropertyElements.xaml b/src/Controls/tests/Xaml.UnitTests/DuplicatePropertyElements.rt.xaml
similarity index 100%
rename from src/Controls/tests/Xaml.UnitTests/DuplicatePropertyElements.xaml
rename to src/Controls/tests/Xaml.UnitTests/DuplicatePropertyElements.rt.xaml
diff --git a/src/Controls/tests/Xaml.UnitTests/DuplicatePropertyElements.xaml.cs b/src/Controls/tests/Xaml.UnitTests/DuplicatePropertyElements.rt.xaml.cs
similarity index 94%
rename from src/Controls/tests/Xaml.UnitTests/DuplicatePropertyElements.xaml.cs
rename to src/Controls/tests/Xaml.UnitTests/DuplicatePropertyElements.rt.xaml.cs
index 9aeb94059318..02f86c858e81 100644
--- a/src/Controls/tests/Xaml.UnitTests/DuplicatePropertyElements.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/DuplicatePropertyElements.rt.xaml.cs
@@ -5,13 +5,12 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Runtime, true)]
public partial class DuplicatePropertyElements : BindableObject
{
public DuplicatePropertyElements() => InitializeComponent();
[TestFixture]
- public static class Tests
+ static class Tests
{
[Test]
public static void ThrowXamlParseException([Values] XamlInflator inflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/DuplicateXArgumentsElements.xaml b/src/Controls/tests/Xaml.UnitTests/DuplicateXArgumentsElements.rt.xaml
similarity index 100%
rename from src/Controls/tests/Xaml.UnitTests/DuplicateXArgumentsElements.xaml
rename to src/Controls/tests/Xaml.UnitTests/DuplicateXArgumentsElements.rt.xaml
diff --git a/src/Controls/tests/Xaml.UnitTests/DuplicateXArgumentsElements.xaml.cs b/src/Controls/tests/Xaml.UnitTests/DuplicateXArgumentsElements.rt.xaml.cs
similarity index 94%
rename from src/Controls/tests/Xaml.UnitTests/DuplicateXArgumentsElements.xaml.cs
rename to src/Controls/tests/Xaml.UnitTests/DuplicateXArgumentsElements.rt.xaml.cs
index aa9bf92e1222..35160eaa76f6 100644
--- a/src/Controls/tests/Xaml.UnitTests/DuplicateXArgumentsElements.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/DuplicateXArgumentsElements.rt.xaml.cs
@@ -5,14 +5,12 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Runtime, true)]
-
public partial class DuplicateXArgumentsElements : BindableObject
{
public DuplicateXArgumentsElements() => InitializeComponent();
[TestFixture]
- public static class Tests
+ static class Tests
{
[Test]
public static void ThrowXamlParseException([Values] XamlInflator inflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/DynamicResource.xaml.cs b/src/Controls/tests/Xaml.UnitTests/DynamicResource.xaml.cs
index 58dc0af7a38c..0e4e40a1aa70 100644
--- a/src/Controls/tests/Xaml.UnitTests/DynamicResource.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/DynamicResource.xaml.cs
@@ -2,7 +2,6 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class DynamicResource : ContentPage
{
public DynamicResource()
@@ -11,7 +10,7 @@ public DynamicResource()
}
[TestFixture]
- public class Tests
+ class Tests
{
[Test]
public void TestDynamicResources([Values] XamlInflator inflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/EventsConnection.xaml.cs b/src/Controls/tests/Xaml.UnitTests/EventsConnection.xaml.cs
index 6d6f142396a3..1c3dcfd54e62 100644
--- a/src/Controls/tests/Xaml.UnitTests/EventsConnection.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/EventsConnection.xaml.cs
@@ -23,7 +23,6 @@ public class ElementWithGenericEvent : ContentView
public void SendClicked() => Clicked?.Invoke(this, new ItemTappedEventArgs("foo", "bar", -1));
}
-[XamlProcessing(XamlInflator.Default, true)]
public partial class EventsConnection : BaseForEvents
{
public EventsConnection()
@@ -53,7 +52,7 @@ public EventsConnection()
static void HandleStaticClicked(object sender, EventArgs e) => staticClicked++;
[TestFixture]
- public class Tests
+ class Tests
{
[Test]
public void TestClicked([Values] XamlInflator inflator)
@@ -120,7 +119,7 @@ public void TestStaticHandler([Values] XamlInflator inflator)
}
}
-public class SubForEvents : EventsConnection
+class SubForEvents : EventsConnection
{
public SubForEvents(XamlInflator inflator) : base(inflator)
{
diff --git a/src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingCtor.xaml b/src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingCtor.rt.xaml
similarity index 100%
rename from src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingCtor.xaml
rename to src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingCtor.rt.xaml
diff --git a/src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingCtor.xaml.cs b/src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingCtor.rt.xaml.cs
similarity index 98%
rename from src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingCtor.xaml.cs
rename to src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingCtor.rt.xaml.cs
index cc3e5e8a902b..62c45ab0ea5b 100644
--- a/src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingCtor.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingCtor.rt.xaml.cs
@@ -8,13 +8,12 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Runtime, true)]
public partial class FactoryMethodMissingCtor : MockView
{
public FactoryMethodMissingCtor() => InitializeComponent();
[TestFixture]
- public class Tests
+ class Tests
{
[Test]
public void Throw([Values] XamlInflator inflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingMethod.xaml b/src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingMethod.rt.xaml
similarity index 100%
rename from src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingMethod.xaml
rename to src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingMethod.rt.xaml
diff --git a/src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingMethod.xaml.cs b/src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingMethod.rt.xaml.cs
similarity index 97%
rename from src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingMethod.xaml.cs
rename to src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingMethod.rt.xaml.cs
index 1bbbc2fb5e17..4cc3124e1abb 100644
--- a/src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingMethod.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/FactoryMethodMissingMethod.rt.xaml.cs
@@ -7,13 +7,12 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Runtime, true)]
public partial class FactoryMethodMissingMethod : MockView
{
public FactoryMethodMissingMethod() => InitializeComponent();
[TestFixture]
- public class Tests
+ class Tests
{
[Test]
public void Throw([Values] XamlInflator inflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/FactoryMethods.xaml.cs b/src/Controls/tests/Xaml.UnitTests/FactoryMethods.xaml.cs
index 484fd796ddaf..0c4e8d8e3f88 100644
--- a/src/Controls/tests/Xaml.UnitTests/FactoryMethods.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/FactoryMethods.xaml.cs
@@ -36,13 +36,12 @@ public class MockFactory
};
}
-[XamlProcessing(XamlInflator.Default, true)]
public partial class FactoryMethods : ContentPage
{
public FactoryMethods() => InitializeComponent();
[TestFixture]
- public class Tests
+ class Tests
{
[Test]
public void TestDefaultCtor([Values] XamlInflator inflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/FieldModifier.xaml.cs b/src/Controls/tests/Xaml.UnitTests/FieldModifier.xaml.cs
index 8ccc8613ec4c..2c0785d97c0b 100644
--- a/src/Controls/tests/Xaml.UnitTests/FieldModifier.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/FieldModifier.xaml.cs
@@ -4,13 +4,12 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class FieldModifier : ContentPage
{
public FieldModifier() => InitializeComponent();
[TestFixture]
- public class FindByNameTests
+ class FindByNameTests
{
[Test]
public void TestFieldModifier([Values] XamlInflator inflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/FindByName.xaml.cs b/src/Controls/tests/Xaml.UnitTests/FindByName.xaml.cs
index 7f0b179fe858..1e2f82eeaa1e 100644
--- a/src/Controls/tests/Xaml.UnitTests/FindByName.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/FindByName.xaml.cs
@@ -2,13 +2,12 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class FindByName : ContentPage
{
public FindByName() => InitializeComponent();
[TestFixture]
- public class FindByNameTests
+ class FindByNameTests
{
[Test]
public void TestRootName([Values] XamlInflator inflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/FontImageExtension.xaml.cs b/src/Controls/tests/Xaml.UnitTests/FontImageExtension.xaml.cs
index 2477675844d6..484921c6bd4f 100644
--- a/src/Controls/tests/Xaml.UnitTests/FontImageExtension.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/FontImageExtension.xaml.cs
@@ -3,7 +3,6 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class FontImageExtension : TabBar
{
public FontImageExtension() => InitializeComponent();
diff --git a/src/Controls/tests/Xaml.UnitTests/FontSize.xaml.cs b/src/Controls/tests/Xaml.UnitTests/FontSize.xaml.cs
index 2eda3ba0bc41..658ca6a12f32 100644
--- a/src/Controls/tests/Xaml.UnitTests/FontSize.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/FontSize.xaml.cs
@@ -7,13 +7,12 @@
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
-[XamlProcessing(XamlInflator.Default, true)]
public partial class FontSize : ContentPage
{
public FontSize() => InitializeComponent();
[TestFixture]
- public class Tests
+ class Tests
{
[Test]
public void FontSizeExtensionsAreReplaced([Values] XamlInflator inflator)
diff --git a/src/Controls/tests/Xaml.UnitTests/GenericCollections.xaml.cs b/src/Controls/tests/Xaml.UnitTests/GenericCollections.xaml.cs
index e00ee29e8e7a..b48caa6204b0 100644
--- a/src/Controls/tests/Xaml.UnitTests/GenericCollections.xaml.cs
+++ b/src/Controls/tests/Xaml.UnitTests/GenericCollections.xaml.cs
@@ -22,13 +22,12 @@ public class GenericCollection : ObservableCollection