Summary
When a UWP project (UseUwp=true) uses the artifacts output layout (UseArtifactsOutput=true), compiled XAML files (XBF) in subdirectories lose their directory prefix when embedded into resources.pri. This causes a runtime XamlParseException with "Cannot locate resource from 'ms-appx:///...'" because the generated code-behind references paths like ms-appx:///Resources/Styles.xaml but the PRI only contains them at the root (e.g., Files/Styles.xbf instead of Files/Resources/Styles.xbf).
Repro
- Create a UWP project targeting
net10.0-windows10.0.26100.0 with UseUwp=true and UseArtifactsOutput=true
- Place a XAML file in a subdirectory, e.g.,
Resources/Styles.xaml with x:Class="MyApp.Resources.Styles"
- Build and run
- App crashes at startup with:
Windows.UI.Xaml.Markup.XamlParseException: XAML parsing failed.
WinRT information: Cannot locate resource from 'ms-appx:///Resources/Styles.xaml'.
Analysis
The XAML compiler generates code-behind that loads XAML via the original relative path:
global::System.Uri resourceLocator = new global::System.Uri("ms-appx:///Resources/Styles.xaml");
However, when UseArtifactsOutput=true redirects the intermediate output to artifacts/obj/<project>/debug/, the build step that populates the PRI layout (filtered.layout.resfiles) loses the subdirectory prefix. The XBF files are listed as flat filenames:
Styles.xbf <-- wrong, should be Resources\Styles.xbf
Templates.xbf <-- wrong, should be Resources\Templates.xbf
Home.xbf <-- wrong, should be Views\Home.xbf
Meanwhile, non-generated content like Assets correctly preserves paths:
Assets\StoreLogo.png <-- correct
The resources.pri dump confirms the mismatch:
<!-- What it generates (wrong): -->
<NamedResource name="Styles.xbf" uri="ms-resource://MyApp/Files/Styles.xbf">
<!-- What it should generate: -->
<NamedResource name="Styles.xbf" uri="ms-resource://MyApp/Files/Resources/Styles.xbf">
Root cause
The _GeneratedXbfFiles items produced by the XAML compiler have full paths under the intermediate output directory (e.g., artifacts/obj/JellyBox/debug/Resources/Styles.xbf). When these items are processed for PRI layout generation, the relative path calculation strips the subdirectory — likely using %(Filename)%(Extension) rather than computing the path relative to $(IntermediateOutputPath).
This does not reproduce without UseArtifactsOutput=true, because the default output layout places intermediate files in a location where the relative path calculation happens to work correctly.
Workaround
Add DisableEmbeddedXbf=true and a target that re-adds the XBF files as Content with correct Link metadata:
<PropertyGroup>
<DisableEmbeddedXbf>true</DisableEmbeddedXbf>
</PropertyGroup>
<Target Name="FixXbfContentPaths" AfterTargets="MarkupCompilePass2">
<ItemGroup>
<Content Include="@(_GeneratedXbfFiles)"
Link="$([MSBuild]::MakeRelative($(IntermediateOutputPath), %(FullPath)))"
CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Target>
Environment
- .NET SDK: 10.0.x
- Windows SDK: 10.0.26100.0
- OS: Windows 11
- Project properties:
UseUwp=true, UseUwpTools=true, UseArtifactsOutput=true
Summary
When a UWP project (
UseUwp=true) uses the artifacts output layout (UseArtifactsOutput=true), compiled XAML files (XBF) in subdirectories lose their directory prefix when embedded intoresources.pri. This causes a runtimeXamlParseExceptionwith "Cannot locate resource from 'ms-appx:///...'" because the generated code-behind references paths likems-appx:///Resources/Styles.xamlbut the PRI only contains them at the root (e.g.,Files/Styles.xbfinstead ofFiles/Resources/Styles.xbf).Repro
net10.0-windows10.0.26100.0withUseUwp=trueandUseArtifactsOutput=trueResources/Styles.xamlwithx:Class="MyApp.Resources.Styles"Analysis
The XAML compiler generates code-behind that loads XAML via the original relative path:
However, when
UseArtifactsOutput=trueredirects the intermediate output toartifacts/obj/<project>/debug/, the build step that populates the PRI layout (filtered.layout.resfiles) loses the subdirectory prefix. The XBF files are listed as flat filenames:Meanwhile, non-generated content like Assets correctly preserves paths:
The
resources.pridump confirms the mismatch:Root cause
The
_GeneratedXbfFilesitems produced by the XAML compiler have full paths under the intermediate output directory (e.g.,artifacts/obj/JellyBox/debug/Resources/Styles.xbf). When these items are processed for PRI layout generation, the relative path calculation strips the subdirectory — likely using%(Filename)%(Extension)rather than computing the path relative to$(IntermediateOutputPath).This does not reproduce without
UseArtifactsOutput=true, because the default output layout places intermediate files in a location where the relative path calculation happens to work correctly.Workaround
Add
DisableEmbeddedXbf=trueand a target that re-adds the XBF files as Content with correctLinkmetadata:Environment
UseUwp=true,UseUwpTools=true,UseArtifactsOutput=true