diff --git a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.Execute.cs
index bf5bdafcc..239efcf6d 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,17 +493,93 @@ public static bool IsObjectSetCallbackImplemented(IPropertySymbol propertySymbol
default: break;
}
- // Check for the remaining well known WinRT projected types
- 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";
+ // Check for the remaining well known WinRT projected types (always available on both UWP and WinAppSDK)
+ 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.
+ 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(fullyQualifiedName) &&
+ HasXamlBindingHelperMethod(compilation, methodName, fullyQualifiedName))
+ {
+ return methodName;
+ }
+ }
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.
///
diff --git a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.cs b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/DependencyPropertyGenerator.cs
index 3f6219eb4..66f9b5360 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(
+ typeSymbol: propertySymbol.Type,
+ useWindowsUIXaml: useWindowsUIXaml,
+ compilation: context.SemanticModel.Compilation);
if (xamlBindingHelperSetMethodName is not null)
{