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#?

Open
#11,812 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area-XamlCompiler bug team-Core team-Markup
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:

Image

Because of this flag, XamlTypeInfoProvider::CreateXamlType() creates an XamlSystemBaseType:

Image

Therefore, for RepeatBehavior, CreateXamlType() returns an XamlSystemBaseType.

The subsequent code checks whether the returned type is an IXamlUserType:

Image

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:

Image

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:

Image

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
  1. Create a new C# WinUI application.

  2. Install the package:

    dotnet add package XamlToolkit.Labs.WinUI.Native --version 0.8.0-alpha
    
  3. Use DataTable, Marquee, or WrapPanel2 in XAML.

  4. Set the relevant properties of the control.

  5. Run the application.

  6. 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.