From 13d207a0d4b82f15be7cb92722fd50d4ac5a7f24 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 afe95fa13de2e87c5e39c5c43a576e4d2414ff53 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 e762dd31b4e34788b349ec8dae5e79863e6b3101 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 7d98da6a1bd686a021dd1e9f6ca0b60db09fe809 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; }