Incorrect code generation for XAML file in a class library
See original GitHub issueDescribe the bug
When a XAML file (page) is in a class library, the wrong generated code is created. This prevents navigating to the page (in a referenced library).
Steps to reproduce the bug
Steps to reproduce the behavior:
- Create a new WinUI 3 app (for desktop or UWP).
- Add a Class library to the same solution.
- Add a blank page to the class library.
- In the app, reference the class library.
- Change the app (in
app.xaml.cs
) so that it navigates to the new blank page rather than MainPage. (e.g.rootFrame.Navigate(typeof(ClassLibrary1.BlankPage1), e.Arguments);
) - Run the app.
- See an unhandled exception. (The exception message is different for UWP & desktop, but the underlying cause is the same: see below.)
There’s also a repro project at https://github.com/microsoft/ProjectReunion/issues/618#issuecomment-803227467
Expected behavior
Navigate to the specified page.
Screenshots
n/a
Version Info
NuGet package version: [WinUI 3 - Project Reunion 0.5 Preview: 0.5.0-prerelease]
Windows app type:
UWP | Win32 |
---|---|
Yes | Yes |
Windows 10 version | Saw the problem? |
---|---|
Insider Build (21296.1010) | Yes |
October 2020 Update (19042) | |
May 2020 Update (19041) | |
November 2019 Update (18363) | |
May 2019 Update (18362) | |
October 2018 Update (17763) | |
April 2018 Update (17134) | |
Fall Creators Update (16299) | |
Creators Update (15063) |
Device form factor | Saw the problem? |
---|---|
Desktop | Yes |
Xbox | |
Surface Hub | |
IoT |
Additional context
Discovered while investigating https://github.com/microsoft/ProjectReunion/issues/618
Here’s what’s going wrong:
The code that is generated (in BlankPage.g.i.cs
) does not account for the path differences when a XAML file is in a class library.
The generated code for BlankPage.InitializeComponent
looks like this.
public void InitializeComponent()
{
if (_contentLoaded)
return;
_contentLoaded = true;
global::System.Uri resourceLocator = new global::System.Uri("ms-appx:///BlankPage1.xaml");
global::Microsoft.UI.Xaml.Application.LoadComponent(this, resourceLocator, global::Microsoft.UI.Xaml.Controls.Primitives.ComponentResourceLocation.Nested);
}
Note the path in the URI. It has specified to look for the XAML (.xbf) file in the root of the package. However, when the library is referenced in an app, the XAML files from the library are included in subdirectory that uses the name of the library. Because the attempt to “LoadComponent” is looking in the wrong path it can’t fid the file and so fails to load.
In a UWP/WinUI2 project, following the above repro steps results in the following path being included in the generated code:
global::System.Uri resourceLocator = new global::System.Uri("ms-appx:///ClassLibrary1/BlankPage1.xaml");
With this path it is possible to load and navigate to the page from a separate library.
FIX: Include the library name in the path within the generated resource path.
Because this issue is based on generated code there is no workaround (as far as I can determine.) This issue:
- prevents the creation of large projects that need to split functionality over multiple libraries.
- prevents the creation (or use) of 3rd party libraries that have functionality that loads UI (pages or controls) from XAML files distributed with the library.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:4
- Comments:6 (3 by maintainers)
Top GitHub Comments
@RealTommyKlein Thanks. workaround code resolves the issue 💯
Thanks for the report - was able to repro this on UWP apps/libraries but not Desktop app/libraries. For UWP, you can workaround it by adding this to your class library’s .csproj anywhere under the
Project
element: