microsoft / microsoft/microsoft-ui-xaml
Why are WinUI types such as GridLength and RepeatBehavior (possibly others) marked as TypeInfo_Flags_IsSystemType in C++/WinRT XamlTypeInfo, causing C++ components to fail when consumed from C#?
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 8.4k
- Forks
- 942
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 105
Description
Describe the bug
When a C++/WinRT component exposes certain WinUI types as public properties, the component cannot be consumed correctly from a C# WinUI application.
For example, the following C++/WinRT component definitions are sufficient to reproduce the issue:
runtimeclass DataColumn : Microsoft.UI.Xaml.Controls.ContentControl
{
Microsoft.UI.Xaml.GridLength DesiredWidth;
}
runtimeclass Marquee : Microsoft.UI.Xaml.Controls.ContentControl
{
Microsoft.UI.Xaml.Media.Animation.RepeatBehavior RepeatBehavior;
}
The issue appears to affect at least:
Microsoft.UI.Xaml.GridLength
Microsoft.UI.Xaml.Media.Animation.RepeatBehavior
and there may be other WinUI types with the same behavior.
C++/WinRT generated XamlTypeInfo
In the C++/WinRT generated TypeInfos, RepeatBehavior is marked with TypeInfo_Flags_IsSystemType:
Because of this flag, XamlTypeInfoProvider::CreateXamlType() creates an XamlSystemBaseType:
Therefore, for RepeatBehavior, CreateXamlType() returns an XamlSystemBaseType.
The subsequent code checks whether the returned type is an IXamlUserType:
Since the result is an XamlSystemBaseType rather than an IXamlUserType, this condition is not entered for RepeatBehavior.
C# generated XamlTypeInfo
The C# XamlTypeInfo generated for the consuming application behaves differently.
For example, the generated code for RepeatBehavior looks like this:
As a result, RepeatBehavior is represented as an XamlUserType and is marked as a return type stub.
Later, the generated C# code performs the following check:
Because RepeatBehavior is represented as an XamlUserType with IsReturnTypeStub == true, this condition is entered.
CheckOtherMetadataProvidersForType() then obtains the framework type from another metadata provider.
That provider returns an XamlSystemBaseType.
The generated C# path subsequently evaluates IsConstructible:
bool XamlSystemBaseType::IsConstructible() const
{
throw ::winrt::hresult_not_implemented {};
}
This results in an E_NOTIMPL exception during XBF metadata processing.
The final error is:
Cannot deserialize XBF metadata property list as 'RepeatBehavior'
was not found in type 'XamlToolkit.Labs.WinUI.Marquee'. [Line: 0 Position: 0]
Difference between the two implementations
The relevant difference can be summarized as follows:
C++/WinRT
RepeatBehavior
|
| TypeInfo_Flags_IsSystemType
v
XamlSystemBaseType
|
| not an IXamlUserType
v
does not enter the fallback path
Whereas the C# generated XamlTypeInfo does:
C#
RepeatBehavior
|
v
XamlUserType
|
| IsReturnTypeStub == true
v
CheckOtherMetadataProvidersForType()
|
v
XamlSystemBaseType
|
v
IsConstructible()
|
v
E_NOTIMPL
|
v
XBF metadata loading fails
Why is this important?
This is important because a C++/WinRT WinUI component can be built and packaged successfully, but fail at runtime when it is consumed and used by a C# WinUI application.
The failure is triggered simply by using a component that contains certain WinUI framework types, such as GridLength or RepeatBehavior. The component itself does not need to expose any unusual or custom type.
Instead of failing at compile time with a clear diagnostic, the failure occurs during XBF/XAML metadata processing, resulting in an error such as:
Cannot deserialize XBF metadata property list as 'RepeatBehavior'
was not found in type 'XamlToolkit.Labs.WinUI.Marquee'.
This makes an otherwise valid C++/WinRT WinUI component unusable from a C# WinUI application.
If other WinUI framework types are affected by the same issue, the impact may extend beyond GridLength and RepeatBehavior and potentially affect a broader range of C++/WinRT components.
The issue is particularly concerning because there is no indication when building the C++/WinRT component that it will fail when consumed from C#. The incompatibility only becomes visible when the C# application actually loads and uses the component.
Steps to reproduce the bug
-
Create a new C# WinUI application.
-
Install the package:
dotnet add package XamlToolkit.Labs.WinUI.Native --version 0.8.0-alpha -
Use
DataTable,Marquee, orWrapPanel2in XAML. -
Set the relevant properties of the control.
-
Run the application.
-
The application crashes during startup/XAML loading.
Actual behavior
The application crashes during XAML/XBF metadata loading when using the C++/WinRT component from a C# WinUI application.
Expected behavior
The application should start and run normally, and the same C++/WinRT component should be usable from both C++ and C# WinUI applications.
Screenshots
No response
NuGet package version
2.4.0
Windows version
No response
Additional context
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the failure with the XamlToolkit.Labs.WinUI.Native package and the DataTable, Marquee, or WrapPanel2 controls. Compare the generated C++/WinRT and C# XamlTypeInfo paths around XamlTypeInfoProvider::CreateXamlType(), CheckOtherMetadataProvidersForType(), and IsConstructible(). Done means the component loads and runs from a C# WinUI application without the XBF metadata error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, csharp
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100