microsoft / microsoft-ui-xaml

Windows UI Library: the latest Windows 10 native controls and Fluent styles for your applications
MIT License
6.28k stars 674 forks source link

Unable to consume custom and/or templated control using nuget packages in WinUi 3 C#/.Net #7830

Open Overrided opened 1 year ago

Overrided commented 1 year ago

Describe the bug

I'm trying to package xaml templated control into nuget package and then consume it in C#/WinUI 3 packaged app. In UWP this was working, but in WinUI 3 it seems to be broken.

In my attempt I was following documentation: CsWinRT Authoring Windows App Sdk Applications, Xaml Templated Controls C# WinUI 3
and samples: CsWinRT AuthoringDemo, WindowsAppSDK CustomControls

Using WindowsAppSDK CustomControls sample as a codebase, I've tried to pack WinUIComponentCs project as nuget package and then use it in CsApp instead of directly referencing projects as it is shown in sample.

Now, if consumer app project directly references custom control project, everything works as expected, all custom controls are available.

But once using same custom control via nuget package, consumer app crashes with Microsoft.UI.Xaml.Markup.XamlParseException: 'XAML parsing failed.' error.

Exception details:
image

Microsoft.UI.Xaml.Markup.XamlParseException
  HResult=0x802B000A
  Message=XAML parsing failed.
  Source=WinRT.Runtime
  StackTrace:
   at WinRT.ExceptionHelpers.<ThrowExceptionForHR>g__Throw|20_0(Int32 hr)

If exception is allowed to propagate further, it shows a bit more details:

Microsoft.UI.Xaml.Markup.XamlParseException
  HResult=0x802B000A
  Message=XAML parsing failed.
  Source=WinRT.Runtime
  StackTrace:
   at WinRT.ExceptionHelpers.<ThrowExceptionForHR>g__Throw|20_0(Int32 hr)
   at ABI.Microsoft.UI.Xaml.IApplicationStaticsMethods.LoadComponent(IObjectReference _obj, Object component, Uri resourceLocator, ComponentResourceLocation componentResourceLocation)
   at CsApp.Scenario2_UserControl.InitializeComponent() in ...\Microsoft samples repos\forks\WindowsAppSDK-Samples\Samples\CustomControls\CsApp\obj\x64\Debug\net6.0-windows10.0.22621.0\win10-x64\Scenario2_UserControl.g.i.cs:line 37
   at CsApp.Scenario2_UserControl..ctor() in ...\Microsoft samples repos\forks\WindowsAppSDK-Samples\Samples\CustomControls\CsApp\Scenario2_UserControl.xaml.cs:line 12
   at CsApp.CsApp_XamlTypeInfo.XamlTypeInfoProvider.Activate_43_Scenario2_UserControl() in ...\Microsoft samples repos\forks\WindowsAppSDK-Samples\Samples\CustomControls\CsApp\obj\x64\Debug\net6.0-windows10.0.22621.0\win10-x64\XamlTypeInfo.g.cs:line 376
   at CsApp.CsApp_XamlTypeInfo.XamlUserType.ActivateInstance() in ...\Microsoft samples repos\forks\WindowsAppSDK-Samples\Samples\CustomControls\CsApp\obj\x64\Debug\net6.0-windows10.0.22621.0\win10-x64\XamlTypeInfo.g.cs:line 1885
   at ABI.Microsoft.UI.Xaml.Markup.IXamlType.Do_Abi_ActivateInstance_13(IntPtr thisPtr, IntPtr* result)
--- End of stack trace from previous location ---

  This exception was originally thrown at this call stack:
    WinRT.ExceptionHelpers.ThrowExceptionForHR.__Throw|20_0(int)
    ABI.Microsoft.UI.Xaml.IApplicationStaticsMethods.LoadComponent(WinRT.IObjectReference, object, System.Uri, Microsoft.UI.Xaml.Controls.Primitives.ComponentResourceLocation)
    CsApp.Scenario2_UserControl.InitializeComponent() in Scenario2_UserControl.g.i.cs
    CsApp.Scenario2_UserControl.Scenario2_UserControl() in Scenario2_UserControl.xaml.cs
    CsApp.CsApp_XamlTypeInfo.XamlTypeInfoProvider.Activate_43_Scenario2_UserControl() in XamlTypeInfo.g.cs
    CsApp.CsApp_XamlTypeInfo.XamlUserType.ActivateInstance() in XamlTypeInfo.g.cs
    ABI.Microsoft.UI.Xaml.Markup.IXamlType.Do_Abi_ActivateInstance_13(System.IntPtr, System.IntPtr*)

For more context and additional testing scenarios please see fork of WindowsAppSDK CustomControls, and follow Steps to reproduce the bug.

Steps to reproduce the bug

  1. Perform dry run to establish baseline in terms of expected behavior.
    1.1. Clone fork of WindowsAppSDK CustomControls
    1.2. Checkout NugetCustomControlBug branch.
    1.3. Navigate to ...\WindowsAppSDK-Samples\Samples\CustomControls subfolder.
    1.4. Open CsWinRTAuthoringWinUI.sln using Visual Studio.
    1.5. Build solution (NOTE: I'm only interested in C#/.Net part of WinUI 3 so far, so no C++-related observations where made).
    1.6. Set CsApp as Startup Project (In Visual Studio -> right click on CsApp project -> select Set as Startup Project).
    1.7. Launch CsApp application in 'packaged' configuration. (In Visual Studio -> press F5).
    1.8. Verify all 3 available scenarios - Custom Control, User Control and Templated Custom Control - are not crashing when CsApp (consumer app) directly references WinUIComponentCs (custom control library). Please see verification in Screenshots section.

  2. Modify CsApp app to consume custom controls using NuGet package and observe crash.
    2.1. Pack WinUIComponentCs project into nuget package (In Visual Studio -> right click on WinUIComponentCs project -> select Pack or using dotnet cli).
    2.2. Copy WinUIComponentCs.1.0.0.nupkg from previos step to ...\WindowsAppSDK-Samples\Samples\localpackages folder.
    2.3. In CsApp remove reference to WinUIComponentCs (In Visual Studio -> Expand CsApp project Dependencies -> expand Projects -> select WinUIComponentCs -> press delete).
    2.4. In CsApp install WinUIComponentCs.1.0.0.nupkg nuget package from step 2.1. (In Visual Studio -> right click on CsApp project -> select Manage Nuget Packages -> set Package source to localpackages -> select Browse tab -> select WinUIComponentCs package in package list -> click Install).
    2.5. Launch CsApp application in 'packaged' configuration. (In Visual Studio -> press F5).
    2.6. Select User Control or Templated Custom Control scenario and observe crash.

NOTE:
Custom Control scenario work no matter if WinUIComponentCs project is referenced directly or consumed via nuget package.
I assume that's because Custom Control scenario demonstrates CustomButton control which is directy inherited from Button and features no custom xaml.

Expected behavior

Expected behavior is same as established in a dry run part of Steps to reproduce the bug - Custom Control, User Control and Templated Custom Control scenarios are working and not crashing CsApp.

Screenshots

Dry run scenarios verification:

image

Consuming WinUIComponentCs as Nuget Package:

  1. User Control failure image

  2. Templated Custom Control failure image

NuGet package version

WinUI 3 - Windows App SDK 1.1.5

Windows app type

Device form factor

Desktop

Windows version

Windows 11 (22H2): Build 22621, Windows 11 (21H2): Build 22000, Windows 10 (21H2): Build 19044, Windows 10 (21H1): Build 19043, Windows 10 (20H2): Build 19042

Additional context

Additional steps to reproduce different errors I was able to reproduce while trying to manually reference xaml markup of custom controls:

Case 1

  1. Uncomment line 20 in CustomControls CsApp App.xaml
  2. Launch CsApp app.
  3. Observe crash - same exception but different message - Cannot locate resource from 'ms-appx://WinUIComponentCs/Themes/Generic.xaml'. [Line: 20 Position: 37] like in this #3371 issue. image

Case 2

  1. Uncomment line 15 in CustomControls CsApp Styles.xaml
  2. Launch CsApp app.
  3. Observe crash - same exception but different message - Failed to assign to property 'Microsoft.UI.Xaml.ResourceDictionary.Source' because the type 'Windows.Foundation.String' cannot be assigned to the type 'Windows.Foundation.Uri'. [Line: 17 Position: 37] like in this issue #6674. image

Case 3

Change WinUIComponentCs's name to something with '.' (dot character) in it - like WinUIComponentCs.Core. Project will still build/pack but would not be referenced by consumer app.

Overrided commented 1 year ago

Hi @bpulliam! Any news on this? I mean it's really needed and basic feature - being able to distribute and reuse custom components using nuget packages.

sam-wheat commented 1 year ago

@bpulliam I am also waiting on this.

Overrided commented 1 year ago

@bpulliam could you please elaborate on when this bug is planned to be fixed? This is show-stopper for me since I can't reuse any templated control without copying code, which is ridiculous to have in goddamn 2023!!

abdes commented 7 months ago

How is this a feature proposal lol... This is clearly a blocking issue.

Overrided commented 7 months ago

@JesseCol I'm glad this is going at least somewhere. Is there any estimate on this feature request?)

michael-hawker commented 5 months ago

@Overrided have you tried using the Windows Community Toolkit controls within your app? We have been packaging and building templated controls on top of WinUI 3 since the beginning without issue. This seems like a doc/sample/configuration issue that's been overlooked somewhere that's led you to this badstate?

(Also seems related to #6452 and https://github.com/microsoft/WindowsAppSDK/issues/3546)

Overrided commented 5 months ago

@michael-hawker nope, didn't use Community toolkit, I've tried custom control in both my and reference solutions from Microsoft and fired this bug. Had no chance to try it with latest .net etc, will check.