From f278ff22a8a03472c1d3edf10530e1dfbe4fe3cb Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 10 Jun 2026 10:27:25 -0700 Subject: [PATCH 1/4] Add helper to probe XamlBindingHelper for optional WinAppSDK setters Introduce a 'HasXamlBindingHelperMethod' helper that resolves the WinAppSDK 'Microsoft.UI.Xaml.Markup.XamlBindingHelper' type from the current 'Compilation' and verifies that a given static 'SetPropertyFrom*' method exists with the expected '(object, DependencyProperty, T)' signature. This unblocks gating optimized codegen on the availability of newer 'XamlBindingHelper' overloads that were added in recent WinAppSDK versions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../DependencyPropertyGenerator.Execute.cs | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs index bf5bdafcc..b72a12e13 100644 --- a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs +++ b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs @@ -502,6 +502,53 @@ public static bool IsObjectSetCallbackImplemented(IPropertySymbol propertySymbol return null; } + /// + /// Checks whether the WinAppSDK XamlBindingHelper type exposes a SetPropertyFrom* static method + /// with the expected (object, DependencyProperty, T) signature. + /// + /// The for the current run. + /// The name of the static method to look for. + /// The fully qualified metadata name of the third (value) parameter. + /// Whether the WinAppSDK XamlBindingHelper exposes a matching static method. + /// + /// This helper intentionally hardcodes the WinAppSDK XamlBindingHelper type, as it is only used + /// to probe for methods that don't exist on the UWP equivalent. Callers must therefore gate on + /// useWindowsUIXaml == false before invoking it. + /// + private static bool HasXamlBindingHelperMethod(Compilation compilation, string methodName, string valueTypeMetadataName) + { + INamedTypeSymbol? xamlBindingHelperType = compilation.GetTypeByMetadataName(WellKnownTypeNames.XamlBindingHelper(useWindowsUIXaml: false)); + + if (xamlBindingHelperType is null) + { + return false; + } + + // Match the expected 'static void Method(object, DependencyProperty, T)' shape. We validate the + // exact parameter types to guard against any future overload with the same name but different shape. + foreach (ISymbol member in xamlBindingHelperType.GetMembers(methodName)) + { + if (member is IMethodSymbol + { + IsStatic: true, + ReturnsVoid: true, + Parameters: + [ + { Type.SpecialType: SpecialType.System_Object }, + { Type: INamedTypeSymbol dependencyPropertyType }, + { Type: INamedTypeSymbol valueType } + ] + } && + dependencyPropertyType.HasFullyQualifiedMetadataName(WellKnownTypeNames.DependencyProperty(useWindowsUIXaml: false)) && + valueType.HasFullyQualifiedMetadataName(valueTypeMetadataName)) + { + return true; + } + } + + return false; + } + /// /// Gathers all forwarded attributes for the generated property. /// From 54b65c537c5e485260bf722800f1895e2d5dd055 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 10 Jun 2026 10:28:11 -0700 Subject: [PATCH 2/4] Optimize DP setter codegen for Color, CornerRadius, and Thickness Extend the optimized 'XamlBindingHelper.SetPropertyFrom*' codegen path to also cover `Color`, `CornerRadius`, and `Thickness` property types when targeting WinAppSDK. The corresponding 'SetPropertyFromColor', 'SetPropertyFromCornerRadius', and 'SetPropertyFromThickness' static methods on 'Microsoft.UI.Xaml.Markup.XamlBindingHelper' were added in WinAppSDK 1.6, and have no equivalent on the UWP 'Windows.UI.Xaml.Markup.XamlBindingHelper'. To avoid breaking codegen when consumers target older WinAppSDK versions, 'GetXamlBindingHelperSetMethodName' now takes the current 'Compilation' and 'useWindowsUIXaml' flag and uses 'HasXamlBindingHelperMethod' to opt in to the new methods only when they actually exist with the expected signature. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../DependencyPropertyGenerator.Execute.cs | 31 +++++++++++++++++-- .../DependencyPropertyGenerator.cs | 5 ++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs index b72a12e13..afd325677 100644 --- a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs +++ b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs @@ -471,8 +471,10 @@ public static bool IsObjectSetCallbackImplemented(IPropertySymbol propertySymbol /// Gets the XamlBindingHelper.SetPropertyFrom* method name for a given property type, if supported. /// /// The input to check. + /// Whether to use the UWP XAML or WinUI 3 XAML namespaces. + /// The for the current run, used to probe for optional APIs. /// The method name to use, or if the type is not supported. - public static string? GetXamlBindingHelperSetMethodName(ITypeSymbol typeSymbol) + public static string? GetXamlBindingHelperSetMethodName(ITypeSymbol typeSymbol, bool useWindowsUIXaml, Compilation compilation) { // Check for well known primitive types first (these are the most common) switch (typeSymbol.SpecialType) @@ -491,7 +493,7 @@ public static bool IsObjectSetCallbackImplemented(IPropertySymbol propertySymbol default: break; } - // Check for the remaining well known WinRT projected types + // Check for the remaining well known WinRT projected types (always available on both UWP and WinAppSDK) if (typeSymbol.HasFullyQualifiedMetadataName("System.DateTimeOffset")) return "SetPropertyFromDateTime"; if (typeSymbol.HasFullyQualifiedMetadataName("System.TimeSpan")) return "SetPropertyFromTimeSpan"; if (typeSymbol.HasFullyQualifiedMetadataName("Windows.Foundation.Point")) return "SetPropertyFromPoint"; @@ -499,6 +501,31 @@ public static bool IsObjectSetCallbackImplemented(IPropertySymbol propertySymbol if (typeSymbol.HasFullyQualifiedMetadataName("Windows.Foundation.Size")) return "SetPropertyFromSize"; if (typeSymbol.HasFullyQualifiedMetadataName("System.Uri")) return "SetPropertyFromUri"; + // The following types only have a corresponding 'SetPropertyFrom*' method on the WinAppSDK + // 'XamlBindingHelper'. The methods were also only added in newer WinAppSDK versions, so we + // additionally have to probe for their presence on the resolved type before emitting calls + // to them, to avoid breaking codegen for projects targeting older WinAppSDK releases. + if (!useWindowsUIXaml) + { + if (typeSymbol.HasFullyQualifiedMetadataName("Windows.UI.Color") && + HasXamlBindingHelperMethod(compilation, "SetPropertyFromColor", "Windows.UI.Color")) + { + return "SetPropertyFromColor"; + } + + if (typeSymbol.HasFullyQualifiedMetadataName($"{WellKnownTypeNames.MicrosoftUIXamlNamespace}.CornerRadius") && + HasXamlBindingHelperMethod(compilation, "SetPropertyFromCornerRadius", $"{WellKnownTypeNames.MicrosoftUIXamlNamespace}.CornerRadius")) + { + return "SetPropertyFromCornerRadius"; + } + + if (typeSymbol.HasFullyQualifiedMetadataName($"{WellKnownTypeNames.MicrosoftUIXamlNamespace}.Thickness") && + HasXamlBindingHelperMethod(compilation, "SetPropertyFromThickness", $"{WellKnownTypeNames.MicrosoftUIXamlNamespace}.Thickness")) + { + return "SetPropertyFromThickness"; + } + } + return null; } diff --git a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.cs b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.cs index 3f6219eb4..c6c1e08c4 100644 --- a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.cs +++ b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.cs @@ -110,7 +110,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Get the optimized XamlBindingHelper method name for the property type, if applicable. // This is only used when the property type is not 'object' (which would gain nothing), // and the user hasn't provided their own 'OnSet(ref object)' implementation. - string? xamlBindingHelperSetMethodName = Execute.GetXamlBindingHelperSetMethodName(propertySymbol.Type); + string? xamlBindingHelperSetMethodName = Execute.GetXamlBindingHelperSetMethodName( + propertySymbol.Type, + useWindowsUIXaml, + context.SemanticModel.Compilation); if (xamlBindingHelperSetMethodName is not null) { From 3f2ba5156645821a4ff71aa463c58b31340822ce Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 10 Jun 2026 11:48:58 -0700 Subject: [PATCH 3/4] Refactor XamlBindingHelper method detection Consolidate repetitive type checks into ReadOnlySpan<(string,string)> loops to map well-known types to their corresponding XamlBindingHelper SetPropertyFrom* methods. Add an early return when useWindowsUIXaml is false to avoid probing WinAppSDK-only APIs on UWP. Combine type name checks with HasXamlBindingHelperMethod calls for WinAppSDK-only types. Also update the call site to use named arguments (typeSymbol, useWindowsUIXaml, compilation) for clarity. --- .../DependencyPropertyGenerator.Execute.cs | 48 ++++++++++--------- .../DependencyPropertyGenerator.cs | 6 +-- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs index afd325677..1baf29223 100644 --- a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs +++ b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs @@ -494,35 +494,39 @@ public static bool IsObjectSetCallbackImplemented(IPropertySymbol propertySymbol } // Check for the remaining well known WinRT projected types (always available on both UWP and WinAppSDK) - if (typeSymbol.HasFullyQualifiedMetadataName("System.DateTimeOffset")) return "SetPropertyFromDateTime"; - if (typeSymbol.HasFullyQualifiedMetadataName("System.TimeSpan")) return "SetPropertyFromTimeSpan"; - if (typeSymbol.HasFullyQualifiedMetadataName("Windows.Foundation.Point")) return "SetPropertyFromPoint"; - if (typeSymbol.HasFullyQualifiedMetadataName("Windows.Foundation.Rect")) return "SetPropertyFromRect"; - if (typeSymbol.HasFullyQualifiedMetadataName("Windows.Foundation.Size")) return "SetPropertyFromSize"; - if (typeSymbol.HasFullyQualifiedMetadataName("System.Uri")) return "SetPropertyFromUri"; + foreach ((string fullyQualifiedName, string methodName) in (ReadOnlySpan<(string, string)>)[ + ("System.DateTimeOffset", "SetPropertyFromDateTime"), + ("System.TimeSpan", "SetPropertyFromTimeSpan"), + ("Windows.Foundation.Point", "SetPropertyFromPoint"), + ("Windows.Foundation.Rect", "SetPropertyFromRect"), + ("Windows.Foundation.Size", "SetPropertyFromSize"), + ("System.Uri", "SetPropertyFromUri")]) + { + if (typeSymbol.HasFullyQualifiedMetadataName(fullyQualifiedName)) + { + return methodName; + } + } + + // UWP is not getting any new APIs in 'XamlBindingHelper', so if we didn't hit a match yet, we can stop here + if (!useWindowsUIXaml) + { + return null; + } // The following types only have a corresponding 'SetPropertyFrom*' method on the WinAppSDK // 'XamlBindingHelper'. The methods were also only added in newer WinAppSDK versions, so we // additionally have to probe for their presence on the resolved type before emitting calls // to them, to avoid breaking codegen for projects targeting older WinAppSDK releases. - if (!useWindowsUIXaml) + foreach ((string fullyQualifiedName, string methodName) in (ReadOnlySpan<(string, string)>)[ + ("Windows.UI.Color", "SetPropertyFromColor"), + ("Microsoft.UI.Xaml.CornerRadius", "SetPropertyFromCornerRadius"), + ("Microsoft.UI.Xaml.Thickness", "SetPropertyFromThickness")]) { - if (typeSymbol.HasFullyQualifiedMetadataName("Windows.UI.Color") && - HasXamlBindingHelperMethod(compilation, "SetPropertyFromColor", "Windows.UI.Color")) - { - return "SetPropertyFromColor"; - } - - if (typeSymbol.HasFullyQualifiedMetadataName($"{WellKnownTypeNames.MicrosoftUIXamlNamespace}.CornerRadius") && - HasXamlBindingHelperMethod(compilation, "SetPropertyFromCornerRadius", $"{WellKnownTypeNames.MicrosoftUIXamlNamespace}.CornerRadius")) - { - return "SetPropertyFromCornerRadius"; - } - - if (typeSymbol.HasFullyQualifiedMetadataName($"{WellKnownTypeNames.MicrosoftUIXamlNamespace}.Thickness") && - HasXamlBindingHelperMethod(compilation, "SetPropertyFromThickness", $"{WellKnownTypeNames.MicrosoftUIXamlNamespace}.Thickness")) + if (typeSymbol.HasFullyQualifiedMetadataName(fullyQualifiedName) && + HasXamlBindingHelperMethod(compilation, methodName, fullyQualifiedName)) { - return "SetPropertyFromThickness"; + return methodName; } } diff --git a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.cs b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.cs index c6c1e08c4..66f9b5360 100644 --- a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.cs +++ b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.cs @@ -111,9 +111,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // This is only used when the property type is not 'object' (which would gain nothing), // and the user hasn't provided their own 'OnSet(ref object)' implementation. string? xamlBindingHelperSetMethodName = Execute.GetXamlBindingHelperSetMethodName( - propertySymbol.Type, - useWindowsUIXaml, - context.SemanticModel.Compilation); + typeSymbol: propertySymbol.Type, + useWindowsUIXaml: useWindowsUIXaml, + compilation: context.SemanticModel.Compilation); if (xamlBindingHelperSetMethodName is not null) { From 51dbd2ef002008d1abe214461bdcd46b38d409ee Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 10 Jun 2026 11:50:42 -0700 Subject: [PATCH 4/4] Fix inverted gate so WinAppSDK-only XamlBindingHelper probes are reachable The early-return guard introduced in the previous commit used '!useWindowsUIXaml', which short-circuited on WinAppSDK and skipped the new 'SetPropertyFromColor', 'SetPropertyFromCornerRadius', and 'SetPropertyFromThickness' probes entirely (the opposite of the intent stated in the inline comment, and of the actual feature this code is meant to enable). Flip the condition to 'useWindowsUIXaml' so we bail out on UWP (which never gets these methods) and continue probing on WinAppSDK. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../DependencyPropertyGenerator.Execute.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs index 1baf29223..239efcf6d 100644 --- a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs +++ b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs @@ -509,7 +509,7 @@ public static bool IsObjectSetCallbackImplemented(IPropertySymbol propertySymbol } // UWP is not getting any new APIs in 'XamlBindingHelper', so if we didn't hit a match yet, we can stop here - if (!useWindowsUIXaml) + if (useWindowsUIXaml) { return null; }