From 3d83a9bc85e446dae3870b2567118eadd4e59cfd Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Tue, 25 Aug 2026 16:21:17 +0530 Subject: [PATCH 01/31] Tabular: widen the dllmain activation carve-out for TableView MuxcActivationHandler fast-pathed every Microsoft.UI.Xaml.* activation to the MUX framework DLL, excluding only the Microsoft.UI.Xaml.Controls.Tabular.* subtree. Tabular also owns Microsoft.UI.Xaml.XamlTypeInfo.XamlControlsTabularXamlMetaDataProvider, which was therefore routed to MUX instead of resolving locally. Add an explicit kTabularOwnedNamespacesOutsideSubtree prefix set, matched on a trailing '.' so a prefix can only ever match a whole namespace component, and drop the resolved TODO. Base-framework routing is unchanged. Validated: Microsoft.UI.Xaml.Controls.vcxproj and Microsoft.UI.Xaml.Controls.Tabular.vcxproj both build with 0 errors / 0 warnings (amd64chk). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f7510cb3-5321-46fb-919b-6234e3262d94 --- controls/dev/dll-tabular/dllmain.cpp | 34 ++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/controls/dev/dll-tabular/dllmain.cpp b/controls/dev/dll-tabular/dllmain.cpp index bde96d1785..4929937d52 100644 --- a/controls/dev/dll-tabular/dllmain.cpp +++ b/controls/dev/dll-tabular/dllmain.cpp @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include // MUXC-parity block: MUXC's dllmain pulls in the material-helper LifetimeHandler here. Inert in the // Tabular binary (MUXCONTROLS_TABULAR is always defined); kept guarded to ease twin-diffing vs MUXC. #ifndef MUXCONTROLS_TABULAR @@ -53,6 +56,22 @@ std::atomic s_muxGetFactory{ nullptr }; std::atomic s_muxFactoryResolved{ false }; std::atomic s_bypassTraceEmitted{ false }; +// Namespace prefixes (each ending in '.') that the Tabular DLL PRODUCES *outside* its own +// Microsoft.UI.Xaml.Controls.Tabular.* subtree. Every runtimeclass compiled into this DLL -- +// see controls\dev\dll-tabular\Microsoft.UI.Xaml.Controls.Tabular.idl and the control IDLs merged +// after it per controls\Tabular.ProjectImports.targets -- lives either under +// Microsoft.UI.Xaml.Controls.Tabular.* (already excluded below) or under one of these prefixes. +// This is the ONE place to add a prefix the next time a Tabular control lands a runtimeclass +// outside that subtree (e.g. a future Automation.Peers/Data carve-out). +// +// Matching requires the trailing '.' so a prefix can only match a full namespace component -- +// e.g. "Microsoft.UI.Xaml.XamlTypeInfo." can never accidentally match an unrelated sibling +// namespace such as "Microsoft.UI.Xaml.XamlTypeInfoSomethingElse.". +constexpr std::array kTabularOwnedNamespacesOutsideSubtree{ + // XamlControlsTabularXamlMetaDataProvider (Microsoft.UI.Xaml.Controls.Tabular.idl, MU_X_XTI_NAMESPACE) + L"Microsoft.UI.Xaml.XamlTypeInfo.", +}; + DllGetActivationFactory_t GetMuxActivationFactoryFn() { if (!s_muxFactoryResolved.load(std::memory_order_acquire)) @@ -150,12 +169,19 @@ int32_t __stdcall MuxcActivationHandler( std::wstring_view name{ buf, len }; if (name.starts_with(L"Microsoft.UI.Xaml.") && - !name.starts_with(L"Microsoft.UI.Xaml.Controls.Tabular.")) + !name.starts_with(L"Microsoft.UI.Xaml.Controls.Tabular.") && + std::none_of( + kTabularOwnedNamespacesOutsideSubtree.begin(), + kTabularOwnedNamespacesOutsideSubtree.end(), + [&name](std::wstring_view prefix) { return name.starts_with(prefix); })) { // Route base framework types (Microsoft.UI.Xaml.*) to the in-proc framework dll (Microsoft.ui.xaml.dll); - // the Tabular subtree falls through here. MUXC controls (Microsoft.UI.Xaml.Controls.*) live in the controls - // dll, not the framework dll, so they don't resolve here and fall through to RoGetActivationFactory below. - // TODO: also carve out Tabular's out-of-subtree types (Automation.Peers/Data/XamlTypeInfo) before controls land. + // the Tabular subtree (Microsoft.UI.Xaml.Controls.Tabular.*) and this Tabular DLL's other own + // namespaces (kTabularOwnedNamespacesOutsideSubtree, above) fall through here instead, so they + // resolve locally via RoGetActivationFactory / this DLL's own factory below. MUXC controls + // (Microsoft.UI.Xaml.Controls.*) live in the controls dll, not the framework dll, so they don't + // resolve here either and fall through the same way. Add new Tabular-owned, out-of-subtree + // namespaces to kTabularOwnedNamespacesOutsideSubtree, not here. auto muxGetFactory = GetMuxActivationFactoryFn(); if (muxGetFactory) { From 5f65b7d4ce48e461a792f38d2f9a4b0a5e5b44ed Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 11:07:20 +0530 Subject: [PATCH 02/31] Tabular: trim the dllmain activation carve-out comments Amends the comment block on the previous commit down to what the code needs; no behaviour change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- controls/dev/dll-tabular/dllmain.cpp | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/controls/dev/dll-tabular/dllmain.cpp b/controls/dev/dll-tabular/dllmain.cpp index 4929937d52..9077d3e451 100644 --- a/controls/dev/dll-tabular/dllmain.cpp +++ b/controls/dev/dll-tabular/dllmain.cpp @@ -56,19 +56,9 @@ std::atomic s_muxGetFactory{ nullptr }; std::atomic s_muxFactoryResolved{ false }; std::atomic s_bypassTraceEmitted{ false }; -// Namespace prefixes (each ending in '.') that the Tabular DLL PRODUCES *outside* its own -// Microsoft.UI.Xaml.Controls.Tabular.* subtree. Every runtimeclass compiled into this DLL -- -// see controls\dev\dll-tabular\Microsoft.UI.Xaml.Controls.Tabular.idl and the control IDLs merged -// after it per controls\Tabular.ProjectImports.targets -- lives either under -// Microsoft.UI.Xaml.Controls.Tabular.* (already excluded below) or under one of these prefixes. -// This is the ONE place to add a prefix the next time a Tabular control lands a runtimeclass -// outside that subtree (e.g. a future Automation.Peers/Data carve-out). -// -// Matching requires the trailing '.' so a prefix can only match a full namespace component -- -// e.g. "Microsoft.UI.Xaml.XamlTypeInfo." can never accidentally match an unrelated sibling -// namespace such as "Microsoft.UI.Xaml.XamlTypeInfoSomethingElse.". +// Tabular-owned namespaces outside its Microsoft.UI.Xaml.Controls.Tabular.* subtree. +// Prefixes end in '.' so they only match a whole namespace component. constexpr std::array kTabularOwnedNamespacesOutsideSubtree{ - // XamlControlsTabularXamlMetaDataProvider (Microsoft.UI.Xaml.Controls.Tabular.idl, MU_X_XTI_NAMESPACE) L"Microsoft.UI.Xaml.XamlTypeInfo.", }; @@ -176,12 +166,8 @@ int32_t __stdcall MuxcActivationHandler( [&name](std::wstring_view prefix) { return name.starts_with(prefix); })) { // Route base framework types (Microsoft.UI.Xaml.*) to the in-proc framework dll (Microsoft.ui.xaml.dll); - // the Tabular subtree (Microsoft.UI.Xaml.Controls.Tabular.*) and this Tabular DLL's other own - // namespaces (kTabularOwnedNamespacesOutsideSubtree, above) fall through here instead, so they - // resolve locally via RoGetActivationFactory / this DLL's own factory below. MUXC controls - // (Microsoft.UI.Xaml.Controls.*) live in the controls dll, not the framework dll, so they don't - // resolve here either and fall through the same way. Add new Tabular-owned, out-of-subtree - // namespaces to kTabularOwnedNamespacesOutsideSubtree, not here. + // the Tabular subtree falls through here. MUXC controls (Microsoft.UI.Xaml.Controls.*) live in the controls + // dll, not the framework dll, so they don't resolve here and fall through to RoGetActivationFactory below. auto muxGetFactory = GetMuxActivationFactoryFn(); if (muxGetFactory) { From 74a828aff99efaa9941e8070a6e20a0c35c0fc19 Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 11:07:20 +0530 Subject: [PATCH 03/31] Tabular: publish TableView through the package and fix theme-resource resolution Removes the workarounds that consuming apps needed for TableView. An app outside the repo can now reference the package and render a TableView with no app-side shims: no projection regeneration, no ActivatableClass injection, no WinMDReference, no metadata-provider chaining. Public metadata Drop the IncludeTabularControlsInPublicMetadata gate so Tabular types reach the public merged winmd and the CsWinRT projection, and emit their activation registrations. Corrects nuspec comments that claimed Tabular was gated out. IDL de-duplication Tabular's IDL redeclared 8 Microsoft.UI.Xaml.CustomAttributes types; reference MUXC's unmerged winmd instead so the merge is clean. idl/dll split Tabular ran MIDL, mdmerge, XamlCompile and link in one project, so XamlCompile only ever saw pre-merge metadata. Split the metadata half into controls/idl-tabular, mirroring how MUXC separates controls/idl from controls/dev/dll. MergedWinMD consumes the unmerged winmd; the dll project runs XamlCompile against the merged public winmd. Theme resources Default styles resolved through the component's resource-map alias, ms-appx://TabularControlsAlias/. That authority does not exist in a consuming app: the app's build expands every reference PRI into its own resources.pri, which erases component root map names, so the lookup threw and took class activation down with it. Use an authority-less ms-appx:/// URI whose path matches AppxPriInitialPath, exactly as MUXC does in XamlControlsResources.cpp. Verified end to end against an external packaged app: UIA reports ControlType.DataGrid with a populated header and rows where it previously reported an empty rectangle and no descendants. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- MergedWinMD/Directory.Build.props | 5 +- ...ojectReunion.WinUI.TransportPackage.nuspec | 2 +- .../Microsoft.WindowsAppSDK.WinUI.nuspec | 4 +- controls/Tabular.ProjectImports.targets | 20 +- .../Microsoft.UI.Xaml.Common.targets | 20 +- .../Microsoft.UI.Xaml.Controls.Tabular.idl | 92 +----- ...Microsoft.UI.Xaml.Controls.Tabular.vcxproj | 23 +- .../dll-tabular/TabularControlsResources.cpp | 13 +- .../XamlMetadataProviderGenerated.h | 293 ++++++++---------- controls/dev/inc/BuildMacros.h | 8 +- ...osoft.UI.Xaml.Controls.Tabular.idl.vcxproj | 167 ++++++++++ eng/productmetadata.props | 7 +- 12 files changed, 367 insertions(+), 287 deletions(-) create mode 100644 controls/idl-tabular/Microsoft.UI.Xaml.Controls.Tabular.idl.vcxproj diff --git a/MergedWinMD/Directory.Build.props b/MergedWinMD/Directory.Build.props index fd7ced7281..e9b1eab67c 100644 --- a/MergedWinMD/Directory.Build.props +++ b/MergedWinMD/Directory.Build.props @@ -1,4 +1,4 @@ - + @@ -57,6 +57,9 @@ --> + + diff --git a/build/nuspecs/Microsoft.ProjectReunion.WinUI.TransportPackage.nuspec b/build/nuspecs/Microsoft.ProjectReunion.WinUI.TransportPackage.nuspec index b8d6e1ecb7..492a9b02d1 100644 --- a/build/nuspecs/Microsoft.ProjectReunion.WinUI.TransportPackage.nuspec +++ b/build/nuspecs/Microsoft.ProjectReunion.WinUI.TransportPackage.nuspec @@ -57,7 +57,7 @@ Please note that the APIs contained in this package are subject to change before - + diff --git a/build/nuspecs/Microsoft.WindowsAppSDK.WinUI.nuspec b/build/nuspecs/Microsoft.WindowsAppSDK.WinUI.nuspec index efd2475011..af1efa48d2 100644 --- a/build/nuspecs/Microsoft.WindowsAppSDK.WinUI.nuspec +++ b/build/nuspecs/Microsoft.WindowsAppSDK.WinUI.nuspec @@ -49,10 +49,10 @@ - + - + diff --git a/controls/Tabular.ProjectImports.targets b/controls/Tabular.ProjectImports.targets index c2d771d926..6116981af7 100644 --- a/controls/Tabular.ProjectImports.targets +++ b/controls/Tabular.ProjectImports.targets @@ -17,17 +17,16 @@ + Swap in the Tabular-renamed metadata IDL: it produces XamlControlsTabularXamlMetaDataProvider + + TabularControlsResources instead of MUXC's XamlControlsXamlMetaDataProvider + XamlControlsResources, + avoiding duplicate-runtimeclass collisions. MIDL also references MUXC's unmerged winmd (below) so + the shared CustomAttributes resolve from there instead of being redeclared here — redeclaring them + caused MDM2009 duplicate-type once both winmds merged into public metadata. Must be the FIRST + @(Midl) entry so its MUX_* macros are visible to every control IDL merged after it. --> + @@ -39,11 +38,6 @@ diff --git a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Common.targets b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Common.targets index b3e61c3488..8c0b42ea75 100644 --- a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Common.targets +++ b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Common.targets @@ -420,9 +420,21 @@ @(XamlIntermediateAssembly->'%(Identity)') - - $(XamlBuildOutputRoot)\controls\dev\dll\Merged\Microsoft.winmd + + $(PublicMergedWinMDDir)\Microsoft.UI.Xaml.winmd + + + + + + + + @@ -452,7 +464,7 @@ OutputPath="$(XamlGeneratedOutputPath)" OutputType="$(OutputType)" ReferenceAssemblyPaths="@(ReferenceAssemblyPaths)" - ReferenceAssemblies="@(ReferencePath);$(IntermediateOutputPath)Merged\Microsoft.winmd;$(MUXCXamlConsumeWinmd)" + ReferenceAssemblies="@(ReferencePath);$(MUXCXamlConsumeWinmd)" ForceSharedStateShutdown="False" CompileMode="RealBuildPass1" XAMLFingerprint="$(XAMLFingerprint)" @@ -499,7 +511,7 @@ OutputPath="$(XamlGeneratedOutputPath)" OutputType="$(OutputType)" ReferenceAssemblyPaths="@(ReferenceAssemblyPaths)" - ReferenceAssemblies="@(XamlReferencesToCompile);$(IntermediateOutputPath)Merged\Microsoft.winmd;$(MUXCXamlConsumeWinmd)" + ReferenceAssemblies="@(XamlReferencesToCompile);$(MUXCXamlConsumeWinmd)" ForceSharedStateShutdown="False" CompileMode="RealBuildPass2" XAMLFingerprint="$(XAMLFingerprint)" diff --git a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.idl b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.idl index 9daa44055a..1ce895f465 100644 --- a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.idl +++ b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.idl @@ -14,22 +14,17 @@ // =========================================================================== // Tabular controls DLL (Microsoft.UI.Xaml.Controls.Tabular) metadata IDL. // -// This is a renamed copy of controls\idl\Microsoft.UI.Xaml.Controls.idl. The -// Tabular DLL references MUXC's component winmd from C++/WinRT (so future tabular -// controls can consume MUXC types -- ItemsRepeater / SelectionModel / ItemsSourceView / -// ItemContainer* etc. -- across the binary boundary, and so the shared Telemetry -// TypeLogging.cpp can stringify MUXC enums). MUXC's winmd already owns -// XamlControlsXamlMetaDataProvider and XamlControlsResources, so the Tabular DLL -// must PRODUCE differently-named types to avoid duplicate-runtimeclass collisions -// in the C++/WinRT projection: XamlControlsTabularXamlMetaDataProvider and -// TabularControlsResources. +// This is a renamed copy of controls\idl\Microsoft.UI.Xaml.Controls.idl. MUXC's +// winmd already owns XamlControlsXamlMetaDataProvider and XamlControlsResources, +// so the Tabular DLL PRODUCEs differently-named types to avoid duplicate-runtimeclass +// collisions: XamlControlsTabularXamlMetaDataProvider and TabularControlsResources. // -// The MUX custom attribute definitions and the MUX_* macros are kept verbatim -// because tabular control IDLs (added later) depend on them. They do NOT collide -// with MUXC's winmd because MIDL never references MUXC's winmd (only C++/WinRT does, -// and C++/WinRT does not project attribute types). This file is the FIRST entry in -// the Tabular project's @(Midl) (see controls\Tabular.ProjectImports.targets) so -// these macros and attributes are visible to all control IDLs merged after it. +// The Microsoft.UI.Xaml.CustomAttributes types (MUXHasCustomActivationFactoryAttribute +// etc.) are NOT redeclared here — MIDL references MUXC's winmd (see +// controls\Tabular.ProjectImports.targets), which already defines them. Only the +// MUX_* macros are kept verbatim, since tabular control IDLs depend on them. This +// file is the FIRST entry in the Tabular project's @(Midl) so those macros are +// visible to all control IDLs merged after it. // =========================================================================== namespace features @@ -43,73 +38,6 @@ namespace features #endif } -namespace Microsoft.UI.Xaml.CustomAttributes -{ - [attributeusage(target_runtimeclass)] - [version(0x00000001)] - [webhosthidden] - attribute MUXHasCustomActivationFactoryAttribute - { - } - - [attributeusage(target_runtimeclass, target_enum, target_struct, target_interface, target_delegate, target_property, target_method)] - [version(0x00000001)] - [webhosthidden] - attribute MUXPropertyNeedsDependencyPropertyFieldAttribute - { - } - - [attributeusage(target_runtimeclass, target_enum, target_struct, target_interface, target_delegate, target_property, target_method)] - [version(0x00000001)] - [webhosthidden] - attribute MUXPropertyChangedCallbackAttribute - { - boolean enable; - } - - [attributeusage(target_runtimeclass, target_enum, target_struct, target_interface, target_delegate, target_property, target_method)] - [version(0x00000001)] - [webhosthidden] - attribute MUXPropertyChangedCallbackMethodNameAttribute - { - String value; - } - - [attributeusage(target_runtimeclass, target_enum, target_struct, target_interface, target_delegate, target_property, target_method)] - [version(0x00000001)] - [webhosthidden] - attribute MUXPropertyValidationCallbackAttribute - { - String value; - } - - [attributeusage(target_property, target_method)] - [version(0x00000001)] - [webhosthidden] - attribute MUXPropertyDefaultValueAttribute - { - String value; - } - - [attributeusage(target_property, target_method)] - [version(0x00000001)] - [webhosthidden] - attribute MUXPropertyTypeAttribute - { - String value; - } - -#include "DPCodeGenAttributes.idl" - - [attributeusage(target_runtimeclass, target_enum, target_struct, target_interface, target_delegate, target_property, target_method)] - [attributename("muxoverrideensureproperties")] - [version(0x00000001)] - [webhosthidden] - attribute MUXOverrideEnsurePropertiesAttribute - { - } -} - // These attributes are used to indicate the state of an API from a consumer's perspective: // * Public (MUX_PUBLIC): Stable and ready to use, API will never change shape // * Preview (MUX_PREVIEW): Ready for experimentation and feedback, API may change diff --git a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj index b11adbe932..ad08a77d9a 100644 --- a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj +++ b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj @@ -15,6 +15,18 @@ NoPageCodeGen;NoTypeInfoCodeGen false + + + true + + TabularControlsAlias + TabularControlsAlias + true + $(MUXTabularTargetName) @@ -22,6 +34,9 @@ + + @@ -34,10 +49,12 @@ $(CppWinRTParameters) -reference "$(XamlBuildOutputRoot)\controls\dev\dll\Unmerged\Microsoft.UI.Xaml.Controls.g.winmd" - + - + diff --git a/controls/dev/dll-tabular/TabularControlsResources.cpp b/controls/dev/dll-tabular/TabularControlsResources.cpp index 6fccfcd111..e935b2072c 100644 --- a/controls/dev/dll-tabular/TabularControlsResources.cpp +++ b/controls/dev/dll-tabular/TabularControlsResources.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. #include "pch.h" @@ -17,12 +17,14 @@ TabularControlsResources::TabularControlsResources() void TabularControlsResources::UpdateSource() { #ifdef TABULAR_BINARY_EMITS_THEME_RESOURCES - // Emit Tabular theme resources only after retargeting these MUXC-rooted URIs and build links together. const bool isPerf2026Enabled = false; // TODO: Decide based on opt-in flag, task.ms/60958581 winrt::Uri uri{ [isPerf2026Enabled]() -> hstring { - hstring packagePrefix = L"ms-appx:///" MUXCONTROLSROOT_NAMESPACE_STR "/Themes/"; + // Authority-less, matching MUXC (XamlControlsResources.cpp). A consuming app's build expands + // every reference PRI into its own resources.pri, which erases component root map names, so + // the alias authority does not exist outside this repo. The path must match AppxPriInitialPath. + hstring packagePrefix = L"ms-appx:///" MUXTABULARROOT_NAMESPACE_STR "/Themes/"; hstring postfix = isPerf2026Enabled ? L"themeresources_perf2026.xaml" : L"themeresources.xaml"; return packagePrefix + postfix; @@ -59,13 +61,12 @@ void SetDefaultStyleKeyWorker(winrt::IControlProtected const& controlProtected, controlProtected.DefaultStyleKey(box_value(className)); #ifdef TABULAR_BINARY_EMITS_THEME_RESOURCES - // Set DefaultStyleResourceUri only after Tabular theme paths are retargeted from MUXC roots. if (auto control = controlProtected.try_as()) { const bool isPerf2026Enabled = false; // TODO: Decide based on opt-in flag, task.ms/60958581 winrt::Uri uri{isPerf2026Enabled - ? L"ms-appx:///" MUXCONTROLSROOT_NAMESPACE_STR "/Themes/generic_perf2026.xaml" - : L"ms-appx:///" MUXCONTROLSROOT_NAMESPACE_STR "/Themes/generic.xaml"}; + ? L"ms-appx:///" MUXTABULARROOT_NAMESPACE_STR "/Themes/generic_perf2026.xaml" + : L"ms-appx:///" MUXTABULARROOT_NAMESPACE_STR "/Themes/generic.xaml"}; control.DefaultStyleResourceUri(uri); } #endif diff --git a/controls/dev/dll-tabular/XamlMetadataProviderGenerated.h b/controls/dev/dll-tabular/XamlMetadataProviderGenerated.h index ae763b57c9..310c14871a 100644 --- a/controls/dev/dll-tabular/XamlMetadataProviderGenerated.h +++ b/controls/dev/dll-tabular/XamlMetadataProviderGenerated.h @@ -101,6 +101,7 @@ Entry c_typeEntries[] = xamlType.AddDPMember(L"Density", L"Microsoft.UI.Xaml.Controls.Tabular.TableViewDensity", statics.DensityProperty(), false /* isContent */); xamlType.AddDPMember(L"EmptyTemplate", L"Microsoft.UI.Xaml.DataTemplate", statics.EmptyTemplateProperty(), false /* isContent */); xamlType.AddDPMember(L"GridLinesVisibility", L"Microsoft.UI.Xaml.Controls.Tabular.TableViewGridLinesVisibility", statics.GridLinesVisibilityProperty(), false /* isContent */); + xamlType.AddDPMember(L"GroupHeaderTemplate", L"Microsoft.UI.Xaml.DataTemplate", statics.GroupHeaderTemplateProperty(), false /* isContent */); xamlType.AddDPMember(L"HeadersVisibility", L"Microsoft.UI.Xaml.Controls.Tabular.TableViewHeadersVisibility", statics.HeadersVisibilityProperty(), false /* isContent */); xamlType.AddDPMember(L"IsReadOnly", L"Boolean", statics.IsReadOnlyProperty(), false /* isContent */); xamlType.AddDPMember(L"ItemsSource", L"Object", statics.ItemsSourceProperty(), false /* isContent */); @@ -263,6 +264,110 @@ Entry c_typeEntries[] = return xamlType; } }, + { + /* Arg1 TypeName */ + L"Microsoft.UI.Xaml.Controls.Tabular.TableViewGroupHeader", + /* Arg2 CreateXamlTypeCallback */ + []() + { + auto xamlType = winrt::make_self( + /* Arg 1 - TypeName */ + (PCWSTR)L"Microsoft.UI.Xaml.Controls.Tabular.TableViewGroupHeader", + /* Arg 2 - BaseTypeName */ + (PCWSTR)L"Microsoft.UI.Xaml.Controls.ContentControl", + /* Arg 3 - Activator func */ + (std::function)[](){ return ActivateInstanceWithFactory(L"Microsoft.UI.Xaml.Controls.Tabular.TableViewGroupHeader"); }, + /* Arg 4 - Populate properties func */ + (std::function)[](XamlTypeBase& xamlType) + { + winrt::ITableViewGroupHeaderStatics statics = GetFactory(L"Microsoft.UI.Xaml.Controls.Tabular.TableViewGroupHeader"); + { + xamlType.AddDPMember(L"IsExpandable", L"Boolean", statics.IsExpandableProperty(), false /* isContent */); + xamlType.AddDPMember(L"IsExpanded", L"Boolean", statics.IsExpandedProperty(), false /* isContent */); + } + + }); + + return static_cast(*xamlType); + } + }, + { + /* Arg1 TypeName */ + L"Microsoft.UI.Xaml.Controls.Tabular.TableViewGroupInfo", + /* Arg2 CreateXamlTypeCallback */ + []() + { + auto xamlType = winrt::make_self( + /* Arg 1 - TypeName */ + (PCWSTR)L"Microsoft.UI.Xaml.Controls.Tabular.TableViewGroupInfo", + /* Arg 2 - BaseTypeName */ + (PCWSTR)L"Object", + /* Arg 3 - Activator func */ + nullptr, + /* Arg 4 - Populate properties func */ + (std::function)[](XamlTypeBase& xamlType) + { + xamlType.AddMember( + L"IsExpandable", /* propertyName */ + L"Boolean", /* propertyType */ + [](winrt::IInspectable instance) { return box_value(instance.as().IsExpandable()); }, + nullptr, /* setter */ + false, /* isContent */ + false, /* isDependencyProperty */ + false /* isAttachable */); + xamlType.AddMember( + L"IsExpanded", /* propertyName */ + L"Boolean", /* propertyType */ + [](winrt::IInspectable instance) { return box_value(instance.as().IsExpanded()); }, + nullptr, /* setter */ + false, /* isContent */ + false, /* isDependencyProperty */ + false /* isAttachable */); + xamlType.AddMember( + L"ItemCount", /* propertyName */ + L"Int32", /* propertyType */ + [](winrt::IInspectable instance) { return box_value(instance.as().ItemCount()); }, + nullptr, /* setter */ + false, /* isContent */ + false, /* isDependencyProperty */ + false /* isAttachable */); + xamlType.AddMember( + L"ItemCountText", /* propertyName */ + L"String", /* propertyType */ + [](winrt::IInspectable instance) { return box_value(instance.as().ItemCountText()); }, + nullptr, /* setter */ + false, /* isContent */ + false, /* isDependencyProperty */ + false /* isAttachable */); + xamlType.AddMember( + L"Key", /* propertyName */ + L"Object", /* propertyType */ + [](winrt::IInspectable instance) { return instance.as().Key(); }, + nullptr, /* setter */ + false, /* isContent */ + false, /* isDependencyProperty */ + false /* isAttachable */); + xamlType.AddMember( + L"KeyText", /* propertyName */ + L"String", /* propertyType */ + [](winrt::IInspectable instance) { return box_value(instance.as().KeyText()); }, + nullptr, /* setter */ + false, /* isContent */ + false, /* isDependencyProperty */ + false /* isAttachable */); + xamlType.AddMember( + L"Level", /* propertyName */ + L"Int32", /* propertyType */ + [](winrt::IInspectable instance) { return box_value(instance.as().Level()); }, + nullptr, /* setter */ + false, /* isContent */ + false, /* isDependencyProperty */ + false /* isAttachable */); + }); + + return static_cast(*xamlType); + } + }, { /* Arg1 TypeName */ L"Microsoft.UI.Xaml.Controls.Tabular.TableViewHeadersVisibility", @@ -404,166 +509,6 @@ Entry c_typeEntries[] = return static_cast(*xamlType); } }, - { - /* Arg1 TypeName */ - L"Microsoft.UI.Xaml.CustomAttributes.MUXHasCustomActivationFactoryAttribute", - /* Arg2 CreateXamlTypeCallback */ - []() - { - auto xamlType = winrt::make_self( - /* Arg 1 - TypeName */ - (PCWSTR)L"Microsoft.UI.Xaml.CustomAttributes.MUXHasCustomActivationFactoryAttribute", - /* Arg 2 - BaseTypeName */ - (PCWSTR)L"Attribute", - /* Arg 3 - Activator func */ - (std::function)[](){ return ActivateInstance(L"Microsoft.UI.Xaml.CustomAttributes.MUXHasCustomActivationFactoryAttribute"); }, - /* Arg 4 - Populate properties func */ - nullptr - ); - - return static_cast(*xamlType); - } - }, - { - /* Arg1 TypeName */ - L"Microsoft.UI.Xaml.CustomAttributes.MUXOverrideEnsurePropertiesAttribute", - /* Arg2 CreateXamlTypeCallback */ - []() - { - auto xamlType = winrt::make_self( - /* Arg 1 - TypeName */ - (PCWSTR)L"Microsoft.UI.Xaml.CustomAttributes.MUXOverrideEnsurePropertiesAttribute", - /* Arg 2 - BaseTypeName */ - (PCWSTR)L"Attribute", - /* Arg 3 - Activator func */ - (std::function)[](){ return ActivateInstance(L"Microsoft.UI.Xaml.CustomAttributes.MUXOverrideEnsurePropertiesAttribute"); }, - /* Arg 4 - Populate properties func */ - nullptr - ); - - return static_cast(*xamlType); - } - }, - { - /* Arg1 TypeName */ - L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyChangedCallbackAttribute", - /* Arg2 CreateXamlTypeCallback */ - []() - { - auto xamlType = winrt::make_self( - /* Arg 1 - TypeName */ - (PCWSTR)L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyChangedCallbackAttribute", - /* Arg 2 - BaseTypeName */ - (PCWSTR)L"Attribute", - /* Arg 3 - Activator func */ - (std::function)[](){ return ActivateInstance(L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyChangedCallbackAttribute"); }, - /* Arg 4 - Populate properties func */ - nullptr - ); - - return static_cast(*xamlType); - } - }, - { - /* Arg1 TypeName */ - L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyChangedCallbackMethodNameAttribute", - /* Arg2 CreateXamlTypeCallback */ - []() - { - auto xamlType = winrt::make_self( - /* Arg 1 - TypeName */ - (PCWSTR)L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyChangedCallbackMethodNameAttribute", - /* Arg 2 - BaseTypeName */ - (PCWSTR)L"Attribute", - /* Arg 3 - Activator func */ - (std::function)[](){ return ActivateInstance(L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyChangedCallbackMethodNameAttribute"); }, - /* Arg 4 - Populate properties func */ - nullptr - ); - - return static_cast(*xamlType); - } - }, - { - /* Arg1 TypeName */ - L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyDefaultValueAttribute", - /* Arg2 CreateXamlTypeCallback */ - []() - { - auto xamlType = winrt::make_self( - /* Arg 1 - TypeName */ - (PCWSTR)L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyDefaultValueAttribute", - /* Arg 2 - BaseTypeName */ - (PCWSTR)L"Attribute", - /* Arg 3 - Activator func */ - (std::function)[](){ return ActivateInstance(L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyDefaultValueAttribute"); }, - /* Arg 4 - Populate properties func */ - nullptr - ); - - return static_cast(*xamlType); - } - }, - { - /* Arg1 TypeName */ - L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyNeedsDependencyPropertyFieldAttribute", - /* Arg2 CreateXamlTypeCallback */ - []() - { - auto xamlType = winrt::make_self( - /* Arg 1 - TypeName */ - (PCWSTR)L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyNeedsDependencyPropertyFieldAttribute", - /* Arg 2 - BaseTypeName */ - (PCWSTR)L"Attribute", - /* Arg 3 - Activator func */ - (std::function)[](){ return ActivateInstance(L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyNeedsDependencyPropertyFieldAttribute"); }, - /* Arg 4 - Populate properties func */ - nullptr - ); - - return static_cast(*xamlType); - } - }, - { - /* Arg1 TypeName */ - L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyTypeAttribute", - /* Arg2 CreateXamlTypeCallback */ - []() - { - auto xamlType = winrt::make_self( - /* Arg 1 - TypeName */ - (PCWSTR)L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyTypeAttribute", - /* Arg 2 - BaseTypeName */ - (PCWSTR)L"Attribute", - /* Arg 3 - Activator func */ - (std::function)[](){ return ActivateInstance(L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyTypeAttribute"); }, - /* Arg 4 - Populate properties func */ - nullptr - ); - - return static_cast(*xamlType); - } - }, - { - /* Arg1 TypeName */ - L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyValidationCallbackAttribute", - /* Arg2 CreateXamlTypeCallback */ - []() - { - auto xamlType = winrt::make_self( - /* Arg 1 - TypeName */ - (PCWSTR)L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyValidationCallbackAttribute", - /* Arg 2 - BaseTypeName */ - (PCWSTR)L"Attribute", - /* Arg 3 - Activator func */ - (std::function)[](){ return ActivateInstance(L"Microsoft.UI.Xaml.CustomAttributes.MUXPropertyValidationCallbackAttribute"); }, - /* Arg 4 - Populate properties func */ - nullptr - ); - - return static_cast(*xamlType); - } - }, { /* Arg1 TypeName */ L"Microsoft.UI.Xaml.XamlTypeInfo.XamlControlsTabularXamlMetaDataProvider", @@ -585,16 +530,6 @@ Entry c_typeEntries[] = } }, // Register types encountered - { - /* Arg1 TypeName */ - L"Attribute", - /* Arg2 CreateXamlTypeCallback */ - []() - { - auto xamlType = winrt::make_self((PCWSTR)L"Attribute", (PCWSTR)L"Object" /* BaseTypeName */ , nullptr /* Activator Func */, nullptr /* PopulatePropertiesFunc */ ); - return static_cast(*xamlType); - } - }, { /* Arg1 TypeName */ L"Boolean", @@ -607,6 +542,12 @@ Entry c_typeEntries[] = /* Arg2 CreateXamlTypeCallback */ []() { return winrt::make((PCWSTR)L"Double"); } }, + { + /* Arg1 TypeName */ + L"Int32", + /* Arg2 CreateXamlTypeCallback */ + []() { return winrt::make((PCWSTR)L"Int32"); } + }, { /* Arg1 TypeName */ L"Microsoft.UI.Private.Controls.SortIndicatorDirection", @@ -630,9 +571,9 @@ Entry c_typeEntries[] = }, { /* Arg1 TypeName */ - L"Int32", + L"Microsoft.UI.Xaml.Controls.ContentControl", /* Arg2 CreateXamlTypeCallback */ - []() { return winrt::make((PCWSTR)L"Int32"); } + []() { return winrt::make((PCWSTR)L"Microsoft.UI.Xaml.Controls.ContentControl"); } }, { /* Arg1 TypeName */ @@ -700,6 +641,12 @@ Entry c_typeEntries[] = /* Arg2 CreateXamlTypeCallback */ []() { return winrt::make((PCWSTR)L"Object"); } }, + { + /* Arg1 TypeName */ + L"String", + /* Arg2 CreateXamlTypeCallback */ + []() { return winrt::make((PCWSTR)L"String"); } + }, { /* Arg1 TypeName */ L"ValueType", @@ -738,6 +685,7 @@ std::wstring_view c_knownNamespacePrefixes[] = #include "SortIndicator.properties.h" #include "TableView.properties.h" #include "TableViewColumn.properties.h" +#include "TableViewGroupHeader.properties.h" #include "TableViewRow.properties.h" #include "TableViewTemplateColumn.properties.h" @@ -748,6 +696,7 @@ void ClearTypeProperties() SortIndicatorProperties::ClearProperties(); TableViewProperties::ClearProperties(); TableViewColumnProperties::ClearProperties(); + TableViewGroupHeaderProperties::ClearProperties(); TableViewRowProperties::ClearProperties(); TableViewTemplateColumnProperties::ClearProperties(); } diff --git a/controls/dev/inc/BuildMacros.h b/controls/dev/inc/BuildMacros.h index 4931ab0afd..898cbf7628 100644 --- a/controls/dev/inc/BuildMacros.h +++ b/controls/dev/inc/BuildMacros.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. #pragma once @@ -10,3 +10,9 @@ #define MUXCONTROLSROOT_NAMESPACE_STR L"Microsoft.UI.Xaml" #define MUXCONTROLSMEDIA_NAMESPACE_STR L"Microsoft.UI.Xaml.Media" + +// Tabular ships its own resource map, so its theme resources are addressed under this root +// rather than MUXC's; sharing MUXC's root caused a PRI277 collision. +#define MUXTABULARROOT_NAMESPACE_STR L"Microsoft.UI.Xaml.Controls.Tabular" +// Resource-map alias: ms-appx authority so lookups bind to this component, not the host process. +#define MUXTABULARALIAS_STR L"TabularControlsAlias" diff --git a/controls/idl-tabular/Microsoft.UI.Xaml.Controls.Tabular.idl.vcxproj b/controls/idl-tabular/Microsoft.UI.Xaml.Controls.Tabular.idl.vcxproj new file mode 100644 index 0000000000..04b75443ff --- /dev/null +++ b/controls/idl-tabular/Microsoft.UI.Xaml.Controls.Tabular.idl.vcxproj @@ -0,0 +1,167 @@ + + + + + + true + false + true + + + + + + + + + + + + + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14} + DynamicLibrary + $(MUXTabularTargetName) + $(MUXNamespace) + en-US + 15.0 + true + Windows Store + 10.0 + ..\..\tools\ + + false + false + false + Microsoft.UI.Xaml.Controls.Tabular.idl + Microsoft.UI.Xaml.Controls.Tabular.idl.pri + + $(XamlBuildOutputRoot)\controls\idl-tabular\ + + + + DynamicLibrary + true + + + DynamicLibrary + false + true + false + + + x64 + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(MSBuildProjectDirectory);$(MUXCProjectRoot)dev;$(LiftedIXPIncludePaths) + $(NoWarn);5135 + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + + + + + false + false + + + + + + + + + + + + + $(ProjectUnmergedWinmd) + + + diff --git a/eng/productmetadata.props b/eng/productmetadata.props index 06b3c36d6d..a86f9be9b7 100644 --- a/eng/productmetadata.props +++ b/eng/productmetadata.props @@ -51,8 +51,10 @@ Condition="Exists('$(WinUIDetailsLibPath)\Microsoft.UI.Xaml.Controls.Charts.winmd')"> Microsoft.UI.Xaml.Controls.Charts.dll - - + + Microsoft.UI.Xaml.Controls.Tabular.dll @@ -88,6 +90,7 @@ + From 060d2c9f3269dc2eca826a126966743012e64dac Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 11:10:55 +0530 Subject: [PATCH 04/31] Tabular: import MUXC's property sheet instead of duplicating it controls\dev\dll-tabular\Microsoft.UI.Xaml.Common.props had drifted into a verbatim copy of controls\dev\dll\Microsoft.UI.Xaml.Common.props plus ten lines, so every MUXC build-setting change had to be mirrored by hand or the two binaries silently diverged. Import the MUXC sheet and keep only the Tabular delta: the MUXCONTROLS_TABULAR define and the conditional TABULAR_BINARY_EMITS_THEME_RESOURCES define. Imported by file-relative path rather than $(MUXCProjectRoot), because the Tabular vcxproj imports this sheet as its first import, before environment.props has defined that property. The MUXC sheet is safe to import from the sibling directory: its only non-property paths are GetPathOfFileAbove(environment.props), which resolves from the MUXC sheet's own location, and ScriptPath="..\..\tools\", which is project-relative and identical for both projects. Verified by rebuilding the Tabular DLL: same 4,209,664-byte output, zero errors. Also refreshes a TableView_themeresources.xaml comment that described theme-XBF emission as still disabled. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../TableView/TableView_themeresources.xaml | 7 +- .../Microsoft.UI.Xaml.Common.props | 76 ++++--------------- 2 files changed, 18 insertions(+), 65 deletions(-) diff --git a/controls/dev/TableView/TableView_themeresources.xaml b/controls/dev/TableView/TableView_themeresources.xaml index 5af7496773..bde0e5a1e4 100644 --- a/controls/dev/TableView/TableView_themeresources.xaml +++ b/controls/dev/TableView/TableView_themeresources.xaml @@ -14,10 +14,9 @@ controls/dev/CommonStyles/TabularSurfaces_themeresources.xaml (with last-resort re-resolving {ThemeResource} fallbacks at the root of TableView.xaml for hosts that do not merge it). The brushes were previously mirrored here too, but that duplicated every - TabularSurface* x:Key in the same Default/Light/HighContrast dictionaries; once Tabular - theme-XBF emission is re-enabled (AB#62822865) the two ThemeResources pages merge and - the overlapping keys would raise a duplicate-key build failure. Keep brushes out of - this page. --> + TabularSurface* x:Key in the same Default/Light/HighContrast dictionaries; with Tabular + theme-XBF emission enabled the two ThemeResources pages merge and the overlapping keys + would raise a duplicate-key build failure. Keep brushes out of this page. --> 40 14 14 diff --git a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Common.props b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Common.props index fde5e85d96..c0eb399318 100644 --- a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Common.props +++ b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Common.props @@ -1,74 +1,28 @@ + - - - - - - - <_ClExternalIncludesSupported> + - true - false - true - - - - $(Platform) - x86 - x64 - - - - - - - - - - - - - en-US - 15.0 - true - Windows Store - 10.0 - - x64 - ..\..\tools\ - true - true - - false - x86|x64|ARM64 - - - - DynamicLibrary - true - - - DynamicLibrary - false - true - false - - - Undefined - Undefined - false - MUXCONTROLS_TABULAR;%(PreprocessorDefinitions) + From 53f8f7e5dc85af1240a91fdf8d9ce06dd4a6412b Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 11:29:19 +0530 Subject: [PATCH 05/31] Tabular: add the metadata project to MUXControlsTabular.sln The solution listed only Microsoft.UI.Xaml.Controls.Tabular.vcxproj, so the metadata project split out alongside it, idl-tabular, was in no solution at all. Build order was unaffected -- MergedWinMD carries a build-order-only ProjectReference to the idl project, and the Tabular DLL carries one to MergedWinMD -- but the project was invisible to Visual Studio and to anything that enumerates the solution. Verified by building the solution: 0 errors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- controls/MUXControlsTabular.sln | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/controls/MUXControlsTabular.sln b/controls/MUXControlsTabular.sln index 747376c6f5..75b54c2cfc 100644 --- a/controls/MUXControlsTabular.sln +++ b/controls/MUXControlsTabular.sln @@ -2,6 +2,8 @@ # Visual Studio Version 17 VisualStudioVersion = 17.2.32526.322 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.UI.Xaml.Controls.Tabular.idl", "idl-tabular\Microsoft.UI.Xaml.Controls.Tabular.idl.vcxproj", "{7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.UI.Xaml.Controls.Tabular", "dev\dll-tabular\Microsoft.UI.Xaml.Controls.Tabular.vcxproj", "{C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}" EndProject Global @@ -44,6 +46,30 @@ Global {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|x64.Build.0 = Release|x64 {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|x86.ActiveCfg = Release|Win32 {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|x86.Build.0 = Release|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|ARM64EC.ActiveCfg = Debug|ARM64EC + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|ARM64EC.Build.0 = Debug|ARM64EC + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|x64.ActiveCfg = Debug|x64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|x64.Build.0 = Debug|x64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|x86.ActiveCfg = Debug|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|x86.Build.0 = Debug|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|ARM64.Build.0 = Debug|ARM64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|ARM64EC.Build.0 = Debug|ARM64EC + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|x64.ActiveCfg = Debug|x64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|x64.Build.0 = Debug|x64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|x86.ActiveCfg = Debug|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|x86.Build.0 = Debug|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|ARM64.ActiveCfg = Release|ARM64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|ARM64.Build.0 = Release|ARM64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|ARM64EC.Build.0 = Release|ARM64EC + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|x64.ActiveCfg = Release|x64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|x64.Build.0 = Release|x64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|x86.ActiveCfg = Release|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 95fe1a312dab1827f412c48f336ee776c6b88110 Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 12:06:51 +0530 Subject: [PATCH 06/31] Tabular: build from MUXControls.sln and retire the second solution Tabular built from its own MUXControlsTabular.sln with a second pipeline step, because the MUXC -> Tabular dependency was sequenced by step order rather than by the project graph: EnsureMuxcComponentWinMDBuilt only *asserts* that MUXC's component winmd is already on disk, and Tabular's references reached MUXC's idl project through MergedWinMD but never the controls DLL that emits that winmd. Declare the missing edge instead. The Tabular DLL now carries a build-order-only ProjectReference to controls\dev\dll\Microsoft.UI.Xaml.Controls.vcxproj, mirroring the one it already has to MergedWinMD. MUXC never references Tabular, so there is no cycle. With the graph complete, both Tabular projects join MUXControls.sln and the separate solution and its pipeline step are deleted as redundant. Verified by building the Tabular target through MUXControls.sln from the solution graph alone: 0 errors. A parallel build on a memory-constrained machine can hit C1076/C3859 while MUXC and Tabular compile together; -m:1 completes cleanly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../WinUI-BuildMUXProject-Steps.yml | 18 +---- controls/MUXControls.sln | 66 +++++++++++++++- controls/MUXControlsTabular.sln | 77 ------------------- ...Microsoft.UI.Xaml.Controls.Tabular.vcxproj | 6 ++ 4 files changed, 74 insertions(+), 93 deletions(-) delete mode 100644 controls/MUXControlsTabular.sln diff --git a/build/AzurePipelinesTemplates/WinUI-BuildMUXProject-Steps.yml b/build/AzurePipelinesTemplates/WinUI-BuildMUXProject-Steps.yml index b06caefdec..aac1ca3d22 100644 --- a/build/AzurePipelinesTemplates/WinUI-BuildMUXProject-Steps.yml +++ b/build/AzurePipelinesTemplates/WinUI-BuildMUXProject-Steps.yml @@ -202,21 +202,9 @@ steps: projectCaching: ${{ parameters.projectCaching }} runStaticAnalysis: ${{ parameters.runStaticAnalysis }} - # Tabular builds from its own MUXControlsTabular.sln rather than from MUXControls.sln: - # Microsoft.UI.Xaml.Controls.Tabular.vcxproj has no ProjectReference to MUXC -- it consumes - # MUXC's already-built component and merged winmds (see EnsureMuxcComponentWinMDBuilt in that - # vcxproj). The dependency is therefore sequenced by step order here rather than inferred from - # a solution graph, so this step MUST stay after the MUXControls.sln step above. - - ${{ if eq(parameters.buildProductOnly, 'false') }}: - - template: WinUI-BuildProject-Steps.yml - parameters: - solutionName: MUXControlsTabular.sln - solutionPath: $(Build.SourcesDirectory)\controls - nugetConfigPath: nuget.config - msBuildArgs: '/p:MUXFinalRelease=${{ parameters.MUXFinalRelease }} ${{ parameters.pgoBuildModeMSBuildArg }} /p:DisableWarnForInvalidRestoreProjects=true ${{parameters.additionalMSBuildOptions}} /p:WinUIVersion=$(versionFinal) /p:PublishAot=$(publishAotValue)' - msbuildInstallDir: $(_buildToolsDirectory) - projectCaching: ${{ parameters.projectCaching }} - runStaticAnalysis: ${{ parameters.runStaticAnalysis }} + # Tabular builds as part of MUXControls.sln. Microsoft.UI.Xaml.Controls.Tabular.vcxproj carries + # build-order-only ProjectReferences to MergedWinMD and to MUXC's controls DLL, so the solution + # graph sequences MUXC -> Tabular on its own and no separate solution or step is needed. - script: | dir /b /s $(Build.SourcesDirectory)\packages\*.nupkg diff --git a/controls/MUXControls.sln b/controls/MUXControls.sln index 0d147ce9e4..7d8543484e 100644 --- a/controls/MUXControls.sln +++ b/controls/MUXControls.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.2.32526.322 @@ -53,6 +53,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{5EF3865D EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.UI.Xaml.Controls", "dev\dll\Microsoft.UI.Xaml.Controls.vcxproj", "{AD0C90B0-4845-4D4B-88F1-86F653F8171B}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.UI.Xaml.Controls.Tabular.idl", "idl-tabular\Microsoft.UI.Xaml.Controls.Tabular.idl.vcxproj", "{7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.UI.Xaml.Controls.Tabular", "dev\dll-tabular\Microsoft.UI.Xaml.Controls.Tabular.vcxproj", "{C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{D3327F36-E161-4FED-A0F4-56F2B735827E}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NavigationView", "NavigationView", "{05CB5DBD-A481-4DFF-B1A3-642F049D165C}" @@ -731,6 +735,66 @@ Global {AD0C90B0-4845-4D4B-88F1-86F653F8171B}.Release|x64.Build.0 = Release|x64 {AD0C90B0-4845-4D4B-88F1-86F653F8171B}.Release|x86.ActiveCfg = Release|Win32 {AD0C90B0-4845-4D4B-88F1-86F653F8171B}.Release|x86.Build.0 = Release|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|ARM64EC.ActiveCfg = Debug|ARM64EC + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|ARM64EC.Build.0 = Debug|ARM64EC + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|Win32.ActiveCfg = Debug|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|Win32.Build.0 = Debug|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|x64.ActiveCfg = Debug|x64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|x64.Build.0 = Debug|x64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|x86.ActiveCfg = Debug|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|x86.Build.0 = Debug|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|ARM64.Build.0 = Debug|ARM64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|ARM64EC.Build.0 = Debug|ARM64EC + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|Win32.ActiveCfg = Debug|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|Win32.Build.0 = Debug|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|x64.ActiveCfg = Debug|x64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|x64.Build.0 = Debug|x64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|x86.ActiveCfg = Debug|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|x86.Build.0 = Debug|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|ARM64.ActiveCfg = Release|ARM64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|ARM64.Build.0 = Release|ARM64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|ARM64EC.Build.0 = Release|ARM64EC + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|Win32.ActiveCfg = Release|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|Win32.Build.0 = Release|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|x64.ActiveCfg = Release|x64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|x64.Build.0 = Release|x64 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|x86.ActiveCfg = Release|Win32 + {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|x86.Build.0 = Release|Win32 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|ARM64EC.ActiveCfg = Debug|ARM64EC + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|ARM64EC.Build.0 = Debug|ARM64EC + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|Win32.ActiveCfg = Debug|Win32 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|Win32.Build.0 = Debug|Win32 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|x64.ActiveCfg = Debug|x64 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|x64.Build.0 = Debug|x64 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|x86.ActiveCfg = Debug|Win32 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|x86.Build.0 = Debug|Win32 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|ARM64.Build.0 = Debug|ARM64 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|ARM64EC.Build.0 = Debug|ARM64EC + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|Win32.ActiveCfg = Debug|Win32 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|Win32.Build.0 = Debug|Win32 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|x64.ActiveCfg = Debug|x64 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|x64.Build.0 = Debug|x64 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|x86.ActiveCfg = Debug|Win32 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|x86.Build.0 = Debug|Win32 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|ARM64.ActiveCfg = Release|ARM64 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|ARM64.Build.0 = Release|ARM64 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|ARM64EC.Build.0 = Release|ARM64EC + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|Win32.ActiveCfg = Release|Win32 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|Win32.Build.0 = Release|Win32 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|x64.ActiveCfg = Release|x64 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|x64.Build.0 = Release|x64 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|x86.ActiveCfg = Release|Win32 + {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|x86.Build.0 = Release|Win32 {92081F61-98BB-4105-A90F-B6D524B4F5C9}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 {92081F61-98BB-4105-A90F-B6D524B4F5C9}.Debug_test|ARM64.Build.0 = Debug|ARM64 {92081F61-98BB-4105-A90F-B6D524B4F5C9}.Debug_test|ARM64.Deploy.0 = Debug|ARM64 diff --git a/controls/MUXControlsTabular.sln b/controls/MUXControlsTabular.sln deleted file mode 100644 index 75b54c2cfc..0000000000 --- a/controls/MUXControlsTabular.sln +++ /dev/null @@ -1,77 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32526.322 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.UI.Xaml.Controls.Tabular.idl", "idl-tabular\Microsoft.UI.Xaml.Controls.Tabular.idl.vcxproj", "{7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.UI.Xaml.Controls.Tabular", "dev\dll-tabular\Microsoft.UI.Xaml.Controls.Tabular.vcxproj", "{C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug_test|ARM64 = Debug_test|ARM64 - Debug_test|ARM64EC = Debug_test|ARM64EC - Debug_test|x64 = Debug_test|x64 - Debug_test|x86 = Debug_test|x86 - Debug|ARM64 = Debug|ARM64 - Debug|ARM64EC = Debug|ARM64EC - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|ARM64 = Release|ARM64 - Release|ARM64EC = Release|ARM64EC - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|ARM64.Build.0 = Debug|ARM64 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|ARM64EC.ActiveCfg = Debug|ARM64EC - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|ARM64EC.Build.0 = Debug|ARM64EC - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|x64.ActiveCfg = Debug|x64 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|x64.Build.0 = Debug|x64 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|x86.ActiveCfg = Debug|Win32 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug_test|x86.Build.0 = Debug|Win32 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|ARM64.Build.0 = Debug|ARM64 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|ARM64EC.Build.0 = Debug|ARM64EC - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|x64.ActiveCfg = Debug|x64 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|x64.Build.0 = Debug|x64 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|x86.ActiveCfg = Debug|Win32 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Debug|x86.Build.0 = Debug|Win32 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|ARM64.ActiveCfg = Release|ARM64 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|ARM64.Build.0 = Release|ARM64 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|ARM64EC.ActiveCfg = Release|ARM64EC - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|ARM64EC.Build.0 = Release|ARM64EC - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|x64.ActiveCfg = Release|x64 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|x64.Build.0 = Release|x64 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|x86.ActiveCfg = Release|Win32 - {C0A0F121-3A2D-4B61-9D5E-8E6B1F4D5B33}.Release|x86.Build.0 = Release|Win32 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|ARM64.Build.0 = Debug|ARM64 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|ARM64EC.ActiveCfg = Debug|ARM64EC - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|ARM64EC.Build.0 = Debug|ARM64EC - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|x64.ActiveCfg = Debug|x64 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|x64.Build.0 = Debug|x64 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|x86.ActiveCfg = Debug|Win32 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug_test|x86.Build.0 = Debug|Win32 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|ARM64.Build.0 = Debug|ARM64 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|ARM64EC.Build.0 = Debug|ARM64EC - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|x64.ActiveCfg = Debug|x64 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|x64.Build.0 = Debug|x64 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|x86.ActiveCfg = Debug|Win32 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Debug|x86.Build.0 = Debug|Win32 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|ARM64.ActiveCfg = Release|ARM64 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|ARM64.Build.0 = Release|ARM64 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|ARM64EC.ActiveCfg = Release|ARM64EC - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|ARM64EC.Build.0 = Release|ARM64EC - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|x64.ActiveCfg = Release|x64 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|x64.Build.0 = Release|x64 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|x86.ActiveCfg = Release|Win32 - {7B6C2C1E-9F0A-4C7B-8E2D-3A9B7F6E5D14}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj index ad08a77d9a..4fd9dd5cf7 100644 --- a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj +++ b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj @@ -37,6 +37,12 @@ + + From 93a8f23ad8e57002b22a9ce8b893c47350dc9596 Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 12:24:35 +0530 Subject: [PATCH 07/31] TableViewSampleApp: correct the docs about package availability README.md and AGENTS.md both told readers TableView "is not yet available through the WindowsAppSDK NuGet package" and that the sample's workarounds "all disappear once the control ships in-box". Both statements are now false: the API reaches the public winmd, activation registrations are emitted, and the control's theme resources ship and resolve, so a packaged app can reference the package and use TableView with no workarounds. The sample's workarounds are not evidence of a product gap. The sample builds unpackaged and self-contained against raw build outputs so the control can be iterated on without a package round-trip, and that configuration is what requires them. Deleting them while the sample still links build outputs breaks it; they retire when the sample is re-pointed at the package. Docs only -- no build or behaviour change. The sample itself is unchanged, and was not rebuilt: this enlistment has no pack.cmd and no nuget.exe, so the mock aggregator package the sample restores against cannot be produced here. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Samples/TableViewSampleApp/AGENTS.md | 28 ++++++++++++++++++---------- Samples/TableViewSampleApp/README.md | 20 +++++++++++++------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/Samples/TableViewSampleApp/AGENTS.md b/Samples/TableViewSampleApp/AGENTS.md index 02001dbab9..7f8cf18408 100644 --- a/Samples/TableViewSampleApp/AGENTS.md +++ b/Samples/TableViewSampleApp/AGENTS.md @@ -6,17 +6,24 @@ end-user quick start lives in [README.md](README.md); this file is the deep refe ## Why this sample is unusual -`TableView` currently ships as a **split binary**: the control lives in -`Microsoft.UI.Xaml.Controls.Tabular.dll`, separate from the main framework DLL, and it is **not -yet exposed through the WindowsAppSDK NuGet package**. A normal WinUI app can't just add a package -reference and use it. To consume the locally built control, the sample: +`TableView` lives in `Microsoft.UI.Xaml.Controls.Tabular.dll`, separate from the main framework DLL. +Its API **is** published through the WindowsAppSDK NuGet package: type information reaches the public +winmd, activation registrations are emitted, and the control's theme resources ship and resolve. A +packaged app that references the package can use `TableView` with **no** workarounds — that path is +covered by a standalone verification app outside the repo. + +This sample is deliberately wired the other way. It builds **unpackaged and self-contained** and +consumes the **freshly built control output** rather than the package, so a developer can iterate on +the control without a package round-trip. To do that it: 1. links the freshly built native control DLL, 2. regenerates its WinRT projection from the freshly built WinMD, and -3. reconstructs, at build and startup time, the pieces the WindowsAppSDK packaging would normally - provide (activatable-class registrations, theme resources, default styles). +3. reconstructs, at build and startup time, the pieces packaged deployment would otherwise provide + (activatable-class registrations, theme resources, default styles). -Every workaround below disappears once `TableView` is delivered in-box through WindowsAppSDK. +Every workaround below is a consequence of that unpackaged, build-output-linked configuration — not +of a gap in the product. They retire when the sample is re-pointed at the package, not merely by +deleting them; removed while the sample still links build outputs, the sample stops working. ## Environment setup @@ -77,9 +84,10 @@ the projected IIDs match the control exactly. ### c. Include the TableView theme resources — sourced from the control, never checked in -The split binary's theme resources are **not** deployed to consuming apps, so the sample compiles -and merges them itself. To guarantee they can never drift from the control, the sample references -the canonical sources directly instead of checking in copies: +The control's theme resources ship in the package and resolve for a packaged app, but this sample is +unpackaged and links build outputs, so nothing deploys them here — it compiles and merges them itself. +To guarantee they can never drift from the control, the sample references the canonical sources +directly instead of checking in copies: - `TabularSurfaces_themeresources.xaml` ← `controls\dev\CommonStyles\TabularSurfaces_themeresources.xaml` - `TableView_themeresources.xaml` ← `controls\dev\TableView\TableView_themeresources.xaml` diff --git a/Samples/TableViewSampleApp/README.md b/Samples/TableViewSampleApp/README.md index f28a25d599..6b31d4f1a8 100644 --- a/Samples/TableViewSampleApp/README.md +++ b/Samples/TableViewSampleApp/README.md @@ -4,10 +4,15 @@ A small, self-contained WinUI 3 desktop app that exercises the live public API o `Microsoft.UI.Xaml.Controls.Tabular.TableView` control. The left panel lets you tweak columns, sizing, headers, grid lines, density, backgrounds, and more while the table updates in real time. -`TableView` currently ships as a **split binary** (`Microsoft.UI.Xaml.Controls.Tabular.dll`) that -is not yet available through the WindowsAppSDK NuGet package, so this sample links the locally built -control and needs a few build workarounds (described below). They all disappear once the control -ships in-box. Deeper architecture notes live in [AGENTS.md](AGENTS.md). +`TableView` ships in `Microsoft.UI.Xaml.Controls.Tabular.dll`, separate from the main framework DLL. +Its API **is** now published through the WindowsAppSDK NuGet package — type information, activation +registrations and theme resources all ship — so an ordinary packaged WinUI app can add a package +reference and use the control with no workarounds at all. + +This sample predates that and is wired differently: it builds **unpackaged and self-contained**, and +links the **freshly built control output** rather than the package, so it can exercise a locally built +control without a package round-trip. That choice, not a gap in the product, is what the workarounds +below exist for. They retire when the sample is re-pointed at the package. ## Prerequisites @@ -37,8 +42,8 @@ which the sample consumes: ### What the sample project does for you -Because `TableView` is a split binary that isn't in WinAppSDK/NuGet yet, the project automates a few -workarounds during build: +Because this sample builds unpackaged and self-contained against raw build outputs rather than +against the package, the project automates a few workarounds during build: - **Stages `Microsoft.UI.Xaml.Controls.Tabular.dll` next to the EXE.** *Why:* the control is a separate binary; without the DLL, activation fails with @@ -47,7 +52,8 @@ workarounds during build: *Why:* keeps the generated projection in sync with the built control and avoids `E_NOINTERFACE` caused by stale metadata. - **Includes the TableView theme resources, sourced directly from the control.** - *Why:* the split binary doesn't deploy its theme resources to consuming apps; without them the + *Why:* the control's theme resources ship in the package, but this sample is unpackaged and links + build outputs, so nothing deploys them here; without them the control renders unstyled or blank. The sample references the control's resources at their canonical locations (and the built `generic.xaml`) rather than checking in copies, so they can never drift from the control. From 0db68ca837f7ac2710017e6b429cd00f0430e496 Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 12:34:30 +0530 Subject: [PATCH 08/31] Tabular: correct the idl project's note about MSB8028 The header comment said this project "intentionally shares controls\idl\" with the MUXC idl project and that the resulting MSB8028 was benign. That is not what the project does: it sets its own IntDir, and both IntDir and IntermediateOutputPath evaluate to BuildOutput\obj\\controls\idl-tabular\. The MSB8028 that prompted the comment came from stale output -- .tlog and FileListAbsolute.txt files left in controls\idl\ by builds predating this project. Deleting the Tabular-named entries there clears the warning with no code change; both idl projects then build with 0 warnings. Comment only; no build or behaviour change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Microsoft.UI.Xaml.Controls.Tabular.idl.vcxproj | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/controls/idl-tabular/Microsoft.UI.Xaml.Controls.Tabular.idl.vcxproj b/controls/idl-tabular/Microsoft.UI.Xaml.Controls.Tabular.idl.vcxproj index 04b75443ff..042a409403 100644 --- a/controls/idl-tabular/Microsoft.UI.Xaml.Controls.Tabular.idl.vcxproj +++ b/controls/idl-tabular/Microsoft.UI.Xaml.Controls.Tabular.idl.vcxproj @@ -10,10 +10,11 @@ project that runs XamlCompile against the merged public winmd cannot be the same project that produces the pre-merge winmd MergedWinMD depends on. - This project intentionally shares controls\idl\ with Microsoft.UI.Xaml.Controls.idl.vcxproj (MSBuild - warns MSB8028 about the shared intermediate directory); all generated file names differ (this project's - IDL/winmd are suffixed ".Tabular"), so the shared directory is benign, and it keeps Tabular's winmd at - the productmetadata.props path other projects already expect. + This project has its own intermediate directory (see IntDir below) so its PRI layout files, which + have fixed names, cannot race the MUXC idl project's. If MSBuild reports MSB8028 claiming this + project shares controls\idl\, that is stale output: .tlog and FileListAbsolute.txt files left in + BuildOutput\obj\\controls\idl\ by builds from before this project existed. Delete the + *Tabular* entries under that directory and the warning goes away; IntDir itself is correct. --> From 19eebbd8cd7317c1e2f38a930bc4f22f6e644e48 Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 12:45:43 +0530 Subject: [PATCH 09/31] TableViewSampleApp: consume the package and delete the workaround machinery The sample hand-wired around the product: it linked raw build output, regenerated its own CsWinRT projection, injected a XAML metadata provider into the app provider's OtherProviders, seeded an internal template part through a never-loaded DataTemplate, compiled the control's theme resources from the control source tree, merged activatable-class registrations into its own app manifest, and staged the Tabular DLL next to the EXE. All of it existed because Tabular's type information was withheld from the public winmd and its theme resources did not resolve. Both of those are fixed, so the sample can be an ordinary consumer. Restructured on the ChartApp samples, which are the existing pattern for a separately-built control set: reference Microsoft.WindowsAppSDK.WinUI, and nothing else. Deleted: TabularMetadataProviderLoader.cs provider injection shim _SplitTypeSeed.xaml XamlTypeInfo seed for TableViewRow Build/MergeIxpAppManifest.ps1 activatable-class manifest merge Removed from the project file: the mock aggregator version override, the CsWinRT projection regeneration and its two targets, the theme-resource Page/Content items sourced from controls\dev, the Tabular DLL staging, and the IXP manifest augmentation block with its three targets. 232 lines to 60. App.xaml.cs drops the provider registration, the deferred resource merges and the diagnostic logging, leaving the standard OnLaunched. App.xaml merges the control's own TabularControlsResources instead of two dictionaries copied from the control source. Verified: builds clean (0 errors) and runs. Every page renders, and the Playground shows text, template, date-picker and image columns bound to live data. The app's own PRI is 3.5 MB, so MUXC's and Tabular's resources both fold into the app resource map as designed. No projection regeneration, no manifest injection, no theme resources compiled from the repo, and no reference into the control tree. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Samples/TableViewSampleApp/App.xaml | 8 +- Samples/TableViewSampleApp/App.xaml.cs | 183 ----------------- .../Build/MergeIxpAppManifest.ps1 | 161 --------------- .../TableViewSampleApp.csproj | 190 ++---------------- .../TabularMetadataProviderLoader.cs | 24 --- .../TableViewSampleApp/_SplitTypeSeed.xaml | 23 --- 6 files changed, 21 insertions(+), 568 deletions(-) delete mode 100644 Samples/TableViewSampleApp/Build/MergeIxpAppManifest.ps1 delete mode 100644 Samples/TableViewSampleApp/TabularMetadataProviderLoader.cs delete mode 100644 Samples/TableViewSampleApp/_SplitTypeSeed.xaml diff --git a/Samples/TableViewSampleApp/App.xaml b/Samples/TableViewSampleApp/App.xaml index 2b91f3dd5c..7823a0e728 100644 --- a/Samples/TableViewSampleApp/App.xaml +++ b/Samples/TableViewSampleApp/App.xaml @@ -8,11 +8,9 @@ - - - + + diff --git a/Samples/TableViewSampleApp/App.xaml.cs b/Samples/TableViewSampleApp/App.xaml.cs index bd9e62ad88..e6b91f2563 100644 --- a/Samples/TableViewSampleApp/App.xaml.cs +++ b/Samples/TableViewSampleApp/App.xaml.cs @@ -1,9 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. -using System; -using System.IO; -using System.Runtime.InteropServices; using Microsoft.UI.Xaml; namespace TableViewSampleApp; @@ -11,194 +8,14 @@ namespace TableViewSampleApp; public partial class App : Application { private Window? _window; - private bool _tabularMetadataRegistered; public App() { InitializeComponent(); - - // SPLIT-BINARY: inject the Tabular DLL's XAML metadata provider into the app provider's - // OtherProviders so the runtime XamlReader.Load in MergeTabularControlsResources() can - // resolve adv:TabularControlsResources (a split-only type in - // Microsoft.UI.Xaml.Controls.Tabular.dll, absent from the build-time projection). Runs - // AFTER InitializeComponent: registering it earlier corrupts Application.Resources - // (get_Resources then throws 0x8000FFFF). - RegisterTabularMetadataProvider(); - - // The TabularControlsResources merge is deliberately deferred to OnLaunched. Accessing - // Application.Resources from the App constructor throws E_UNEXPECTED (0x8000FFFF) in this - // self-contained split config; by OnLaunched the projection is live and the merge succeeds. - - UnhandledException += OnUnhandledException; - } - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - private static extern void OutputDebugStringW(string lpOutputString); - - private static void LogSplit(string message) - { - var line = "[TabularSplit] " + message; - try { OutputDebugStringW(line); } catch { /* best effort */ } - try - { - File.AppendAllLines( - Path.Combine(AppContext.BaseDirectory, "tabular-split-diag.txt"), - new[] { $"{DateTimeOffset.UtcNow:O} {line}" }); - } - catch { /* best effort */ } - } - - /// - /// Appends the Tabular DLL XAML metadata provider to the generated app provider's - /// OtherProviders list so the runtime XamlReader.Load that merges TabularControlsResources - /// can resolve types that live only in the split Microsoft.UI.Xaml.Controls.Tabular.dll. - /// - private void RegisterTabularMetadataProvider() - { - try - { - var provider = TabularMetadataProviderLoader.Create(); - - const System.Reflection.BindingFlags flags = - System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic; - - var appType = typeof(App); - object? appProvider = - appType.GetProperty("_AppProvider", flags)?.GetValue(this) - ?? appType.GetField("__appProvider", flags)?.GetValue(this); - if (appProvider is null) - { - LogSplit("Could not locate the generated app metadata provider (_AppProvider)."); - return; - } - - var metaType = appProvider.GetType(); - object? typeInfoProvider = - metaType.GetProperty("Provider", flags)?.GetValue(appProvider) - ?? metaType.GetField("_provider", flags)?.GetValue(appProvider); - if (typeInfoProvider is null) - { - LogSplit("Could not locate the inner XamlTypeInfoProvider (Provider/_provider)."); - return; - } - - var tipType = typeInfoProvider.GetType(); - var list = - (tipType.GetProperty("OtherProviders", flags)?.GetValue(typeInfoProvider) - ?? tipType.GetField("_otherProviders", flags)?.GetValue(typeInfoProvider)) - as System.Collections.IList; - if (list is null) - { - LogSplit("Could not locate the OtherProviders list on the XamlTypeInfoProvider."); - return; - } - - if (provider is null) - { - LogSplit("Tabular metadata provider loader returned null; skipping registration."); - return; - } - - list.Add(provider); - _tabularMetadataRegistered = true; - LogSplit($"Tabular metadata provider registered; OtherProviders count = {list.Count}."); - } - catch (Exception ex) - { - LogSplit("RegisterTabularMetadataProvider failed: " + ex); - } - } - - private void MergeTabularControlsResources() - { - // Wrap TabularControlsResources inside an outer ResourceDictionary parsed by the native - // XAML reader. XamlReader resolves "adv:TabularControlsResources" through the Application's - // IXamlMetadataProvider chain, into which the Tabular DLL's provider was injected above. - const string xaml = - "" + - "" + - "" + - "" + - ""; - - Microsoft.UI.Xaml.ResourceDictionary? rd; - try - { - var loaded = Microsoft.UI.Xaml.Markup.XamlReader.Load(xaml); - rd = loaded as Microsoft.UI.Xaml.ResourceDictionary; - if (rd is null) - { - LogSplit("Merge: XamlReader returned " + (loaded?.GetType().FullName ?? "null") + " (not ResourceDictionary)."); - return; - } - LogSplit("Merge: XamlReader.Load OK; TabularControlsResources constructed natively."); - } - catch (Exception ex) - { - LogSplit("Merge: XamlReader.Load THREW: " + ex.GetType().FullName + " :: " + ex.Message); - return; - } - - try - { - Resources.MergedDictionaries.Add(rd); - LogSplit($"Merge: TabularControlsResources merged; count = {Resources.MergedDictionaries.Count}."); - } - catch (Exception ex) - { - LogSplit("Merge: Resources.Add THREW: " + ex.GetType().FullName + " (0x" + ex.HResult.ToString("X8") + ") :: " + ex.Message); - } - } - - private void MergeTabularControlStyles() - { - // SPLIT-BINARY: TableView's default Style + ControlTemplate live in the Tabular control's - // generic.xaml (app-compiled here at Microsoft.UI.Xaml\Microsoft.UI.Xaml.Controls.Tabular\ - // Themes\generic.xaml -> ms-appx:///Microsoft.UI.Xaml/Microsoft.UI.Xaml.Controls.Tabular/ - // Themes/generic.xbf, the exact DefaultStyleResourceUri the control computes). Merge it into - // App.Resources so TableView / TableViewRow get their templates (an implicit App-level Style - // outranks the default style). Runs after the metadata provider registration so the slice's - // controls: type names resolve. - try - { - var styles = new Microsoft.UI.Xaml.ResourceDictionary - { - Source = new System.Uri("ms-appx:///Microsoft.UI.Xaml/Microsoft.UI.Xaml.Controls.Tabular/Themes/generic.xaml") - }; - Resources.MergedDictionaries.Add(styles); - LogSplit($"Merge: Tabular control styles merged; count = {Resources.MergedDictionaries.Count}."); - } - catch (Exception ex) - { - LogSplit("Merge: Tabular control styles THREW: " + ex.GetType().FullName + - " (0x" + ex.HResult.ToString("X8") + ") :: " + ex.Message); - } - } - - private void OnUnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) - { - LogSplit($"UnhandledException {e.Exception.GetType().FullName}: {e.Exception.Message}"); - LogSplit(e.Exception.ToString()); } protected override void OnLaunched(LaunchActivatedEventArgs args) { - // SPLIT-BINARY: now that app bootstrap is finished, Application.Resources is reachable. - // Merge TabularControlsResources (brushes) then the Tabular style slice (Style/Template) - // before the window inflates a TableView; without them TableView inflates with no template - // and its native MeasureOverride throws on first layout. - if (_tabularMetadataRegistered) - { - MergeTabularControlsResources(); - MergeTabularControlStyles(); - } - else - { - LogSplit("Skipping explicit Tabular resource merges; provider registration was unavailable."); - } - _window = new MainWindow(); _window.Activate(); } diff --git a/Samples/TableViewSampleApp/Build/MergeIxpAppManifest.ps1 b/Samples/TableViewSampleApp/Build/MergeIxpAppManifest.ps1 deleted file mode 100644 index 5b7d1eaa83..0000000000 --- a/Samples/TableViewSampleApp/Build/MergeIxpAppManifest.ps1 +++ /dev/null @@ -1,161 +0,0 @@ -#requires -Version 5.1 -<# -.SYNOPSIS - Merges the WinAppSDK InteractiveExperiences component-package appxfragment - into a side-by-side assembly manifest that augments the sample app's - app.manifest (DPI awareness only) with the lifted-WinRT activatable-class - registrations missing from the mock aggregator's WindowsAppRuntime MSIX. - -.WHY - TableViewSampleApp is built self-contained + unpackaged (WindowsAppSdkSelfContained=true, - WindowsPackageType=None). The mock NuGet package - `Microsoft.WindowsAppSDK.999.0.0-mock-3.0.0-dev-x64-Debug` ships a - WindowsAppRuntime.1.8-Dev MSIX whose AppxManifest.xml lacks entries for the - separately-shipped InteractiveExperiences component DLLs (CoreMessagingXP.dll, - Microsoft.UI.Dispatching, Microsoft.UI.Input, Microsoft.UI.Windowing, - Microsoft.Graphics.Display, Microsoft.UI.Designer, Microsoft.UI.dll, dcompi.dll, - wuceffectsi.dll). Without these activatable-class entries the app crashes at - startup with REGDB_E_CLASSNOTREG when DispatcherQueueController is activated. - -.WHAT - Reads the side-by-side assembly format expected by mt.exe (the same format - emitted by GenerateAppManifestFromAppx in the mock pkg's SelfContained.targets, - lines 177-306), produces an augmented manifest that mt.exe will then merge with - the SDK-generated WindowsAppSDK.manifest to produce the final embedded manifest. - -.PARAMETER Base - Path to the sample's user app.manifest (DPI awareness etc.). - -.PARAMETER Fragment - Path to the IE component package's runtimes-framework\package.appxfragment. - -.PARAMETER Out - Path to write the augmented manifest. -#> -[CmdletBinding()] -param( - [Parameter(Mandatory=$true)][string]$Base, - [Parameter(Mandatory=$true)][string]$Fragment, - [Parameter(Mandatory=$true)][string]$Out -) - -$ErrorActionPreference = 'Stop' - -# Escapes a string for safe inclusion in an XML attribute value (single-quoted attributes). -function Escape-XmlAttr([string]$value) -{ - if ($null -eq $value) { return '' } - return $value.Replace('&', '&').Replace('<', '<').Replace('>', '>').Replace("'", ''').Replace('"', '"') -} - -if (-not (Test-Path -LiteralPath $Base)) { throw "Base manifest not found: $Base" } -if (-not (Test-Path -LiteralPath $Fragment)) { throw "Component appxfragment not found: $Fragment" } - -# Load fragment with namespace awareness. -[xml]$fragXml = Get-Content -LiteralPath $Fragment -Raw -$nsmgr = New-Object System.Xml.XmlNamespaceManager($fragXml.NameTable) -$nsmgr.AddNamespace('m', 'http://schemas.microsoft.com/appx/manifest/foundation/windows10') - -$ipsNodes = $fragXml.SelectNodes('/m:Fragment/m:Extensions/m:Extension/m:InProcessServer', $nsmgr) -if ($null -eq $ipsNodes -or $ipsNodes.Count -eq 0) { - $ipsNodes = $fragXml.SelectNodes('/m:Package/m:Extensions/m:Extension/m:InProcessServer', $nsmgr) -} -if ($null -eq $ipsNodes -or $ipsNodes.Count -eq 0) { - throw "No elements found in fragment: $Fragment (XML namespace or schema mismatch?)" -} - -# Sentinel class we must see in the output -- if missing, the merge produced nothing useful. -$requiredSentinel = 'Microsoft.UI.Dispatching.DispatcherQueueController' - -# Build the augmented manifest as text (mirrors GenerateAppManifestFromAppx's emission style). -[System.Text.StringBuilder]$sb = [System.Text.StringBuilder]::new() -[void]$sb.AppendLine("") -[void]$sb.AppendLine("") - -# Re-emit the base manifest's only. We intentionally DROP the -# block (dpiAware/dpiAwareness etc.) because SXS treats it as a -# config-manifest section that is invalid inside the binding-style assembly -# manifest that mt.exe produces for WinRT activation. Including it causes the -# OS loader to reject the EXE with ERROR_SXS_CANT_GEN_ACTCTX -# ("side-by-side configuration is incorrect"). DPI awareness for self-contained -# WinUI3 apps comes from the bootstrapper / Microsoft.UI.Windowing APIs. -[xml]$baseXml = Get-Content -LiteralPath $Base -Raw -$baseNsmgr = New-Object System.Xml.XmlNamespaceManager($baseXml.NameTable) -$baseNsmgr.AddNamespace('asm', 'urn:schemas-microsoft-com:asm.v1') - -$baseIdentity = $baseXml.SelectSingleNode('/asm:assembly/asm:assemblyIdentity', $baseNsmgr) -if ($null -ne $baseIdentity) { - # Hand-emit to avoid the redundant xmlns attribute that XmlElement.OuterXml - # adds (SXS resolver is finicky about default-namespace duplication). - $idVersion = $baseIdentity.GetAttribute('version') - if ([string]::IsNullOrEmpty($idVersion)) { $idVersion = '1.0.0.0' } - $idName = $baseIdentity.GetAttribute('name') - if ([string]::IsNullOrEmpty($idName)) { $idName = 'TableViewSampleApp.app' } - [void]$sb.AppendLine(" ") -} else { - [void]$sb.AppendLine(" ") -} - -$classCount = 0 -$dllCount = 0 -foreach ($ips in $ipsNodes) { - $pathNode = $ips.SelectSingleNode('./m:Path', $nsmgr) - if ($null -eq $pathNode) { continue } - $dll = $pathNode.InnerText - [void]$sb.AppendLine(" ") - foreach ($cls in $ips.SelectNodes('./m:ActivatableClass', $nsmgr)) { - $name = $cls.GetAttribute('ActivatableClassId') - if ([string]::IsNullOrEmpty($name)) { continue } - $threading = $cls.GetAttribute('ThreadingModel') - if ([string]::IsNullOrEmpty($threading)) { $threading = 'both' } else { $threading = $threading.ToLowerInvariant() } - [void]$sb.AppendLine(" ") - $classCount++ - } - [void]$sb.AppendLine(" ") - $dllCount++ -} -# --- Split-binary Tabular.dll registration --------------------------------- -# The Tabular control ships in a SEPARATE lifted-WinRT binary -# (Microsoft.UI.Xaml.Controls.Tabular.dll) whose runtimeclasses are NOT present in -# the IXP component fragment above. Without these entries the app fail-fasts with -# 0x80040111 CLASS_E_CLASSNOTAVAILABLE the instant it activates -# XamlControlsTabularXamlMetaDataProvider / TableView. This list is the set of -# activatable runtimeclasses in the built Tabular winmds -# (controls\dev\dll-tabular\Merged\*.winmd); enums are not activatable and are omitted. -[void]$sb.AppendLine(" ") -foreach ($tabularClass in @( - 'Microsoft.UI.Xaml.Controls.Tabular.TableView', - 'Microsoft.UI.Xaml.Controls.Tabular.TableViewColumn', - 'Microsoft.UI.Xaml.Controls.Tabular.TableViewTextColumn', - 'Microsoft.UI.Xaml.Controls.Tabular.TableViewTemplateColumn', - 'Microsoft.UI.Xaml.Controls.Tabular.TableViewRow', - 'Microsoft.UI.Xaml.Controls.Tabular.TableViewCellsPanel', - 'Microsoft.UI.Xaml.Controls.Tabular.TabularControlsResources', - 'Microsoft.UI.Xaml.Controls.Tabular.TableViewAutomationPeer', - 'Microsoft.UI.Xaml.Controls.Tabular.TableViewRowAutomationPeer', - 'Microsoft.UI.Xaml.Controls.Tabular.TableViewColumnHeaderAutomationPeer', - 'Microsoft.UI.Xaml.Controls.Tabular.TableViewCellAutomationPeer', - 'Microsoft.UI.Xaml.XamlTypeInfo.XamlControlsTabularXamlMetaDataProvider' -)) { - [void]$sb.AppendLine(" ") - $classCount++ -} -[void]$sb.AppendLine(" ") -$dllCount++ - -[void]$sb.AppendLine("") - -$result = $sb.ToString() - -if ($result -notmatch [regex]::Escape($requiredSentinel)) { - throw "Augmented manifest does not contain required activatable class '$requiredSentinel' -- fragment parse produced $classCount classes across $dllCount DLLs but the sentinel is missing." -} - -$outDir = Split-Path -Parent $Out -if (-not (Test-Path -LiteralPath $outDir)) { New-Item -ItemType Directory -Force -Path $outDir | Out-Null } -[System.IO.File]::WriteAllText($Out, $result, [System.Text.Encoding]::UTF8) - -Write-Host "MergeIxpAppManifest: wrote $Out -- $dllCount DLLs, $classCount activatable classes." diff --git a/Samples/TableViewSampleApp/TableViewSampleApp.csproj b/Samples/TableViewSampleApp/TableViewSampleApp.csproj index 710ee55e83..4f1184738a 100644 --- a/Samples/TableViewSampleApp/TableViewSampleApp.csproj +++ b/Samples/TableViewSampleApp/TableViewSampleApp.csproj @@ -1,56 +1,27 @@ - - - <_TabularNativeFlavor Condition="'$(Configuration)' == 'Release'">amd64fre - <_TabularNativeFlavor Condition="'$(_TabularNativeFlavor)' == ''">amd64chk - <_MuxcPackagingConfig Condition="'$(Configuration)' == 'Release'">Release - <_MuxcPackagingConfig Condition="'$(_MuxcPackagingConfig)' == ''">Debug - - <_TabularControlsDir>$(MSBuildProjectDirectory)\..\..\controls\dev - <_TabularBuiltDir>$(MSBuildProjectDirectory)\..\..\BuildOutput\obj\$(_TabularNativeFlavor)\controls\dev\dll-tabular - - - - $(Configuration) - 999.0.0-mock-$(WinUIVersion)-$(BuildPlatform)-$(WindowsAppSdkPackageConfig) - WinExe - net8.0-windows10.0.19041.0 + $(SamplesTargetFrameworkMoniker) 10.0.17763.0 TableViewSampleApp app.manifest - x86;x64;ARM64 - win-x86;win-x64;win-arm64 - win-x86 - win-x64 - win-arm64 - win-x64 + x86;x64;ARM64;ARM64EC + win-x86;win-x64;win-arm64 + win10-x86;win10-x64;win10-arm64 + win-x64 + true + win-$(Platform).pubxml true - - true - false - true - false - true - false - None - false - true - $(DefineConstants);DISABLE_XAML_GENERATED_MAIN - false + true + TableViewSampleApp + Debug;Release;Debug_test enable latest - true + + $(DefineConstants);DISABLE_XAML_GENERATED_MAIN $(NoWarn);CS8305 - false @@ -67,141 +38,16 @@ - - - TabularSurfaces_themeresources.xaml - - - TabularSurfaces_themeresources.xaml - PreserveNewest - - - TableView_themeresources.xaml - - - TableView_themeresources.xaml - PreserveNewest - - - Microsoft.UI.Xaml\Microsoft.UI.Xaml.Controls.Tabular\Themes\generic.xaml - - - - Microsoft.UI.Xaml.Controls.Tabular.dll - PreserveNewest - false - - - - - - + + - - - + + - - false - true - 10.0.22621.0 - true - --exclude Windows --include Microsoft.UI.Xaml.XamlTypeInfo.XamlControlsTabularXamlMetaDataProvider --include Microsoft.UI.Xaml.XamlTypeInfo.IXamlControlsTabularXamlMetaDataProvider --include Microsoft.UI.Xaml.XamlTypeInfo.IXamlControlsTabularXamlMetaDataProviderStatics --include Microsoft.UI.Xaml.Controls.Tabular - - - - - - - - - - - - - - - - - - <_IxpPackagesDir>$(MSBuildProjectDirectory)\..\..\packages - <_IxpRid>$(RuntimeIdentifier) - <_IxpRid Condition="'$(_IxpRid)' == ''">win-x64 - <_IxpRid Condition="$(_IxpRid.StartsWith('win10-'))">$(_IxpRid.Replace('win10-', 'win-')) - <_IxpLegacyRid>$(_IxpRid.Replace('win-', 'win10-')) - <_IxpBaseAppManifest>$(MSBuildProjectDirectory)\app.manifest - <_IxpMergeScript>$(MSBuildProjectDirectory)\Build\MergeIxpAppManifest.ps1 - <_IxpAugmentedManifest>$(IntermediateOutputPath)IxpAugmentedAppManifest.manifest + + true - - - <_IxpFragmentInput Include="$(_IxpPackagesDir)\Microsoft.WindowsAppSDK.InteractiveExperiences.*\runtimes-framework\package.appxfragment" /> - <_IxpRuntimeDll Include="$(_IxpPackagesDir)\Microsoft.WindowsAppSDK.InteractiveExperiences.*\runtimes-framework\$(_IxpRid)\native\*.dll" /> - - %(Filename)%(Extension) - PreserveNewest - PreserveNewest - false - - - - - - - - - - - - - - - - - $(_IxpAugmentedManifest) - - - diff --git a/Samples/TableViewSampleApp/TabularMetadataProviderLoader.cs b/Samples/TableViewSampleApp/TabularMetadataProviderLoader.cs deleted file mode 100644 index a552a765f9..0000000000 --- a/Samples/TableViewSampleApp/TabularMetadataProviderLoader.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See LICENSE in the project root for license information. -// -// SPLIT-BINARY consumption shim: in the split layout TableView and its family live in -// Microsoft.UI.Xaml.Controls.Tabular.dll, whose XAML metadata is exposed by -// Microsoft.UI.Xaml.XamlTypeInfo.XamlControlsTabularXamlMetaDataProvider. Initialize() wires -// its activation so the app metadata provider chain can resolve the Tabular template types. - -namespace TableViewSampleApp; - -internal static class TabularMetadataProviderLoader -{ - /// - /// Initializes the Tabular XAML metadata provider from the split control DLL and returns the - /// provider instance so the caller can insert it into the app metadata provider's - /// OtherProviders chain. This is what lets the runtime XamlReader.Load resolve the split-only - /// Tabular template types (e.g. adv:TabularControlsResources). - /// - public static Microsoft.UI.Xaml.Markup.IXamlMetadataProvider? Create() - { - Microsoft.UI.Xaml.XamlTypeInfo.XamlControlsTabularXamlMetaDataProvider.Initialize(); - return new Microsoft.UI.Xaml.XamlTypeInfo.XamlControlsTabularXamlMetaDataProvider(); - } -} diff --git a/Samples/TableViewSampleApp/_SplitTypeSeed.xaml b/Samples/TableViewSampleApp/_SplitTypeSeed.xaml deleted file mode 100644 index e767a93cc2..0000000000 --- a/Samples/TableViewSampleApp/_SplitTypeSeed.xaml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - From 5cb867ab61cdac8bedd89ffa5608d7e68c295b3f Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 12:46:59 +0530 Subject: [PATCH 10/31] TableViewSampleApp: rewrite the docs for a sample with no workarounds README.md and AGENTS.md documented a build that no longer exists: staging the control DLL, regenerating the projection, compiling theme resources from the control source, self-contained unpackaged layout, and the IXP manifest merge. Rewritten for what the sample now is -- an ordinary consumer of Microsoft.WindowsAppSDK.WinUI, modelled on the ChartApp samples. Documents the two things a reader actually needs: merge TabularControlsResources alongside XamlControlsResources, and expect CS8305/WMC1501 because TableView is MUX_PREVIEW. AGENTS.md keeps a short record of what the removed machinery was and lists the three product invariants to check if anyone ever needs it back, so the history is not lost with the code. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Samples/TableViewSampleApp/AGENTS.md | 208 ++++++--------------------- Samples/TableViewSampleApp/README.md | 85 +++++------ 2 files changed, 79 insertions(+), 214 deletions(-) diff --git a/Samples/TableViewSampleApp/AGENTS.md b/Samples/TableViewSampleApp/AGENTS.md index 7f8cf18408..4430209d25 100644 --- a/Samples/TableViewSampleApp/AGENTS.md +++ b/Samples/TableViewSampleApp/AGENTS.md @@ -1,189 +1,65 @@ -# TableView sample — build & setup notes (for agents and maintainers) +# TableView sample — build notes -This document explains **how** the sample is built and **why** each non-obvious step exists. The -end-user quick start lives in [README.md](README.md); this file is the deep reference for anyone -(human or automation) that needs to reproduce, debug, or maintain the build. +The end-user quick start is in [README.md](README.md). This file records how the sample is wired +and why, for anyone maintaining it. -## Why this sample is unusual +## There is nothing unusual here any more -`TableView` lives in `Microsoft.UI.Xaml.Controls.Tabular.dll`, separate from the main framework DLL. -Its API **is** published through the WindowsAppSDK NuGet package: type information reaches the public -winmd, activation registrations are emitted, and the control's theme resources ship and resolve. A -packaged app that references the package can use `TableView` with **no** workarounds — that path is -covered by a standalone verification app outside the repo. +The sample used to hand-wire around the product, because `TableView`'s type information was withheld +from the public winmd and its theme resources did not resolve in a consuming app. It linked raw build +output, regenerated its own CsWinRT projection, injected a XAML metadata provider, seeded an internal +template part into `XamlTypeInfo`, compiled the control's theme resources out of the control source +tree, merged activatable-class registrations into its own app manifest, and staged the control DLL +next to the EXE. -This sample is deliberately wired the other way. It builds **unpackaged and self-contained** and -consumes the **freshly built control output** rather than the package, so a developer can iterate on -the control without a package round-trip. To do that it: +None of that is needed. The project file is now ~60 lines and the sample is an ordinary package +consumer, modelled on the [ChartApp](../ChartApp) samples — the existing pattern in this repo for a +separately-built control set. -1. links the freshly built native control DLL, -2. regenerates its WinRT projection from the freshly built WinMD, and -3. reconstructs, at build and startup time, the pieces packaged deployment would otherwise provide - (activatable-class registrations, theme resources, default styles). +If you find yourself reaching for one of those workarounds again, that is a signal the product +regressed. Check, in order: -Every workaround below is a consequence of that unpackaged, build-output-linked configuration — not -of a gap in the product. They retire when the sample is re-pointed at the package, not merely by -deleting them; removed while the sample still links build outputs, the sample stops working. +1. Tabular types are in the public merged winmd (`MergedWinMD`), not gated out. +2. `` registrations are emitted — they derive from the same merge inputs, so a + withheld winmd silently removes them too. +3. The control's theme XBFs ship in the package and its default-style URI is authority-less + `ms-appx:///`, matching the path in `AppxPriInitialPath`. -## Environment setup - -1. Install Visual Studio 2022 with the **Desktop development with C++** and **.NET Desktop** - workloads. -2. From the repo root, run a full initialization once so packages are restored and the build - environment is provisioned: - - ``` - .\init.cmd - ``` - - For one-shot commands in an already-initialized enlistment, `initrun.ps1 ` sets up the - environment for a single invocation without persisting a shell. - -## Step 1 — Build the Tabular control +## How it builds ``` -.\initrun.ps1 controls\Build.cmd tabular +.\initrun.ps1 msb /q /restore Samples\TableViewSampleApp\TableViewSampleApp.csproj /p:Platform=x64 ``` -Produces: - -- `BuildOutput\obj\amd64chk\controls\dev\dll-tabular\Microsoft.UI.Xaml.Controls.Tabular.dll` -- `BuildOutput\obj\amd64chk\controls\dev\dll-tabular\Merged\*.winmd` (the metadata the sample - projects against) -- `BuildOutput\obj\amd64chk\controls\dev\dll-tabular\generic.xaml` (the default Style / - ControlTemplate slice the sample compiles) - -The sample consumes these outputs directly, so the control must be built **before** the sample. - -## Step 2 — Build the sample +`Microsoft.WindowsAppSDK.WinUI` resolves at `$(WinUIVersion)` through Central Package Versions. To +test a locally built control, pack the component and override that version: ``` -.\initrun.ps1 msb /q /restore Samples\TableViewSampleApp\TableViewSampleApp.csproj /p:Platform=x64 /p:RuntimeIdentifier=win-x64 +.\pack.component.cmd /version 3.0.0-mylocal +... /p:WinUIVersion=3.0.0-mylocal ``` -The project (`TableViewSampleApp.csproj`) performs several workarounds during this build. Each -is described below with the failure it prevents. - -### a. Stage the control DLL next to the executable - -The native `Microsoft.UI.Xaml.Controls.Tabular.dll` is copied next to the app. TableView's -runtime classes are registered (see step *e*) but cannot activate without the DLL present. - -*Prevents:* `CLASS_E_CLASSNOTAVAILABLE` (`0x80040111`) when a `TableView` is first activated. - -### b. Regenerate the CsWinRT projection from the built WinMD - -The mock WindowsAppSDK projection can carry stale `Microsoft.UI.Xaml.Controls.Tabular` metadata. -When the built control's interface IIDs diverge from the stale projection, calls such as -`TableView.get_Columns` fail their `QueryInterface`. The project regenerates the projection with -CsWinRT from the freshly built WinMD (`CsWinRTFilters` include the -`Microsoft.UI.Xaml.Controls.Tabular` namespace and the Tabular XAML metadata provider types) so -the projected IIDs match the control exactly. - -*Prevents:* `E_NOINTERFACE` from stale metadata. - -### c. Include the TableView theme resources — sourced from the control, never checked in - -The control's theme resources ship in the package and resolve for a packaged app, but this sample is -unpackaged and links build outputs, so nothing deploys them here — it compiles and merges them itself. -To guarantee they can never drift from the control, the sample references the canonical sources -directly instead of checking in copies: - -- `TabularSurfaces_themeresources.xaml` ← `controls\dev\CommonStyles\TabularSurfaces_themeresources.xaml` -- `TableView_themeresources.xaml` ← `controls\dev\TableView\TableView_themeresources.xaml` -- `generic.xaml` (default `Style` + `ControlTemplate`) ← the freshly built - `BuildOutput\...\dll-tabular\generic.xaml` - -These are wired via ``/`` items with `` metadata (see the theme-resources -`ItemGroup` in the csproj), app-compiled to the same ms-appx paths the app expects, and merged at -startup by `App.xaml` / `App.xaml.cs`. - -*Prevents:* the control rendering unstyled or blank; its native `MeasureOverride` throwing on -first layout when the template is missing. - -### d. Build self-contained and unpackaged - -The project sets `WindowsAppSdkSelfContained=true`, `WindowsPackageType=None`. This bundles the -WindowsAppRuntime framework natives and emits the in-process-server activation entries that the -packaged bootstrap would otherwise inject. - -*Prevents:* startup failure (`0xC000027B`) on machines lacking a matching framework package. This -is standard WindowsAppSDK behavior for unpackaged apps, not a defect. - -### e. Merge the InteractiveExperiences (IXP) app manifest - -`Build\MergeIxpAppManifest.ps1` merges the WindowsAppSDK InteractiveExperiences component package -`appxfragment` into the app's side-by-side manifest, adding the lifted-WinRT activatable-class -registrations (CoreMessaging, Dispatching, Input, Windowing, etc.) that the mock aggregator's -runtime MSIX omits. It also emits registrations for the split Tabular runtimeclasses (enumerated -from the built Tabular WinMDs), and stages the per-RID native component DLLs next to the executable. - -*Prevents:* `REGDB_E_CLASSNOTREG` at startup when `DispatcherQueueController` is activated, and -`CLASS_E_CLASSNOTAVAILABLE` when the Tabular metadata provider / `TableView` is activated. - -### f. Register the Tabular metadata provider and merge styles at runtime - -`App.xaml.cs`: - -- Injects the Tabular DLL's XAML metadata provider into the generated app provider's - `OtherProviders` (after `InitializeComponent`) so a runtime `XamlReader.Load` can resolve - split-only types such as `TabularControlsResources`. If the provider can't be loaded, the sample - skips the explicit resource merges rather than proceeding without it. -- Defers merging `TabularControlsResources` and the control's `generic.xaml` styles to - `OnLaunched`, because `Application.Resources` is not reachable from the `App` constructor in this - self-contained split configuration (accessing it early throws `E_UNEXPECTED` / `0x8000FFFF`). - -### g. Seed the internal template part into XamlTypeInfo - -`_SplitTypeSeed.xaml` references `TableViewRow` inside a never-loaded `DataTemplate` so the XAML -compiler emits an app-level `XamlTypeInfo` entry for that internal template part. - -*Prevents:* "type `TableViewRow` not found" at inflation time (`0xC000027B`). - -### Type disambiguation in code - -`MainWindow.xaml.cs` uses `using` aliases to bind `TableView*` names to the real -`Microsoft.UI.Xaml.Controls.Tabular.*` types, disambiguating them from the stale mock -`Microsoft.UI.Xaml.Controls.*` projection that the mock framework DLL still carries. - -## Step 3 — Run and verify - -Launch: - -``` -BuildOutput\obj\amd64chk\Samples\TableViewSampleApp\TableViewSampleApp.exe -``` - -The app writes a diagnostic log next to the executable, `tabular-split-diag.txt`. A healthy -startup looks like: - -``` -[TabularSplit] Tabular metadata provider registered; OtherProviders count = 2. -[TabularSplit] Merge: XamlReader.Load OK; TabularControlsResources constructed natively. -[TabularSplit] Merge: TabularControlsResources merged; count = 4. -[TabularSplit] Merge: Tabular control styles merged; count = 5. -``` - -If the window appears and the log shows the four lines above with no `THREW`/`UnhandledException` -entries, the split-binary consumption is working. - -## Configuration → flavor mapping +The control DLL, its `.pri` and its theme XBFs arrive from the package. The consuming app's build +expands every referenced `.pri` and re-indexes it into the app's own `TableViewSampleApp.pri`, which +is why that file is several megabytes: it contains MUXC's and Tabular's resources as well as the +sample's. -The project maps `Configuration` to the matching native control flavor so it stages the correct -bits: +## Two things worth knowing -- `Debug` → `amd64chk` -- `Release` → `amd64fre` +**Merge `TabularControlsResources`.** `App.xaml` merges it next to `XamlControlsResources`. The +control finds its own `generic.xaml` unaided, so without this the table still renders — but the +column header row and the theme brushes are missing, which looks like a control bug and is not one. -Build the Tabular control in the flavor that matches the configuration you build the sample in. +**`TableView` is `[MUX_PREVIEW]`.** C# usage raises `CS8305`, suppressed via `NoWarn` in the project +file. XAML usage raises `WMC1501` once per page; those are deliberately left visible. -## Mock WindowsAppSDK package version +## Entry point -Samples that consume the locally built split-binary controls need a mock `WindowsAppSdkPackageVersion` -so the app resolves the local mock NuGet layout. This is defined **in the sample's own csproj**, so -adding the sample requires no repo-wide build changes. +`Program.cs` provides `Main` and the project defines `DISABLE_XAML_GENERATED_MAIN`, following the +[DisableXamlGeneratedMain](../DisableXamlGeneratedMain) sample. This is a normal WinUI pattern, not a +workaround. ## Known issue -An `EmptyTemplate` containing a `FontIcon` can crash at startup while the empty state is first -shown. Prefer text or shape content in the `EmptyTemplate` until this is resolved. +An `EmptyTemplate` containing a `FontIcon` can crash at startup while the empty state is first shown. +Prefer text or shape content in the `EmptyTemplate` until this is resolved. diff --git a/Samples/TableViewSampleApp/README.md b/Samples/TableViewSampleApp/README.md index 6b31d4f1a8..5ea1931144 100644 --- a/Samples/TableViewSampleApp/README.md +++ b/Samples/TableViewSampleApp/README.md @@ -1,18 +1,14 @@ # TableView sample -A small, self-contained WinUI 3 desktop app that exercises the live public API of the +A small WinUI 3 desktop app that exercises the live public API of the `Microsoft.UI.Xaml.Controls.Tabular.TableView` control. The left panel lets you tweak columns, sizing, headers, grid lines, density, backgrounds, and more while the table updates in real time. -`TableView` ships in `Microsoft.UI.Xaml.Controls.Tabular.dll`, separate from the main framework DLL. -Its API **is** now published through the WindowsAppSDK NuGet package — type information, activation -registrations and theme resources all ship — so an ordinary packaged WinUI app can add a package -reference and use the control with no workarounds at all. - -This sample predates that and is wired differently: it builds **unpackaged and self-contained**, and -links the **freshly built control output** rather than the package, so it can exercise a locally built -control without a package round-trip. That choice, not a gap in the product, is what the workarounds -below exist for. They retire when the sample is re-pointed at the package. +`TableView` ships in `Microsoft.UI.Xaml.Controls.Tabular.dll`, separate from the main framework DLL, +but its API is published through the WindowsAppSDK NuGet package: type information reaches the +public winmd, activation registrations are emitted, and the control's theme resources ship and +resolve. So this sample is an **ordinary consumer** — it references the package and does nothing +special, exactly like the [ChartApp](../ChartApp) samples. ## Prerequisites @@ -27,56 +23,51 @@ below exist for. They retire when the sample is re-pointed at the package. From the repo root: -**1. Build the Tabular control** — produces `Microsoft.UI.Xaml.Controls.Tabular.dll` and its WinMD, -which the sample consumes: - ``` -.\initrun.ps1 controls\Build.cmd tabular +.\initrun.ps1 msb /q /restore Samples\TableViewSampleApp\TableViewSampleApp.csproj /p:Platform=x64 ``` -**2. Build the sample:** +The sample resolves `Microsoft.WindowsAppSDK.WinUI` at `$(WinUIVersion)`. To run against a locally +built control, pack the component and point the build at that version: ``` -.\initrun.ps1 msb /q /restore Samples\TableViewSampleApp\TableViewSampleApp.csproj /p:Platform=x64 /p:RuntimeIdentifier=win-x64 +.\pack.component.cmd /version 3.0.0-mylocal +.\initrun.ps1 msb /q /restore Samples\TableViewSampleApp\TableViewSampleApp.csproj /p:Platform=x64 /p:WinUIVersion=3.0.0-mylocal ``` -### What the sample project does for you - -Because this sample builds unpackaged and self-contained against raw build outputs rather than -against the package, the project automates a few workarounds during build: - -- **Stages `Microsoft.UI.Xaml.Controls.Tabular.dll` next to the EXE.** - *Why:* the control is a separate binary; without the DLL, activation fails with - `CLASS_E_CLASSNOTAVAILABLE`. -- **Regenerates the CsWinRT projection from the freshly built WinMD.** - *Why:* keeps the generated projection in sync with the built control and avoids `E_NOINTERFACE` - caused by stale metadata. -- **Includes the TableView theme resources, sourced directly from the control.** - *Why:* the control's theme resources ship in the package, but this sample is unpackaged and links - build outputs, so nothing deploys them here; without them the - control renders unstyled or blank. The sample references the control's resources at their - canonical locations (and the built `generic.xaml`) rather than checking in copies, so they can - never drift from the control. -- **Builds as a self-contained, unpackaged app** (`WindowsAppSdkSelfContained=true`, - `WindowsPackageType=None`). - *Why:* bundles the required Windows App Runtime dependencies for unpackaged execution. -- **Merges the InteractiveExperiences app manifest.** - *Why:* registers the activatable classes missing from the local mock package; without it, startup - fails with `REGDB_E_CLASSNOTREG`. - ## Run -The self-contained, unpackaged executable is produced at: - ``` BuildOutput\obj\amd64chk\Samples\TableViewSampleApp\TableViewSampleApp.exe ``` -Launch it directly — the required control DLL and runtime dependencies are staged alongside it. +## Using TableView in your own app -## What it demonstrates +Two things, both ordinary: -The left panel exercises these live-tweakable API surfaces: +1. Reference `Microsoft.WindowsAppSDK.WinUI`. +2. Merge the control's theme dictionary alongside `XamlControlsResources`, so its brushes and + metrics are in scope: + + ```xml + + + + + + + + + ``` + + Without the second dictionary the control still gets its template, but the column header row and + the theme brushes will be missing. + +`TableView` is `[MUX_PREVIEW]`, so C# usage raises `CS8305` and XAML usage raises `WMC1501` +("for evaluation purposes only"). This sample suppresses `CS8305`; the XAML warnings are left +visible on purpose. + +## What it demonstrates - Column `Width` (Auto / Pixel / Star), `MinWidth`, `MaxWidth` - Add / remove / hide columns @@ -97,6 +88,4 @@ first shown. Prefer text or shape content in the `EmptyTemplate` until this is r ## More detail -For the full build architecture — why the projection is regenerated, why the app is built -self-contained and unpackaged, how the theme resources and control DLL are staged, and how the -app manifest is augmented — see [AGENTS.md](AGENTS.md). +See [AGENTS.md](AGENTS.md). From c70959530062c8210a762468bf8069303c345552 Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 14:22:50 +0530 Subject: [PATCH 11/31] Tabular: scrub an internal reference and drop the now-dead alias macro Three review findings against this branch. OSS-safety: Microsoft.UI.Xaml.Controls.Tabular.vcxproj carried "See OSClient PR 16542065" in a comment. This repo mirrors publicly and comments mirror verbatim, so an internal PR number must not ship. Rewritten to keep the technical substance with no internal marker. Correctness: the same comment, and one in BuildMacros.h, asserted that resources resolve through the component's resource-map alias rather than ms-appx:///, because ms-appx:/// "would bind to the hosting process's package". The control now does exactly the opposite, deliberately: a consuming app's build expands every referenced PRI into its own resources.pri and drops component root-map names, so binding to the hosting process's package is what works. Both comments now describe shipped behaviour and point at TabularControlsResources.cpp. Dead code: MUXTABULARALIAS_STR had zero references once the URIs stopped using it -- one occurrence in the tree, its own definition. Removed. The XamlResourceMapName and ProjectPriIndexName properties keep the alias string, since those still name the root map of the standalone .pri. Build verified: 0 warnings, 0 errors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj | 7 +++++-- controls/dev/inc/BuildMacros.h | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj index 4fd9dd5cf7..409bfeae05 100644 --- a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj +++ b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj @@ -21,8 +21,11 @@ (ms-appx:///Microsoft.UI.Xaml.Controls.Tabular/Themes/...). Without this they collide with MUXC's Microsoft.UI.Xaml root on merge (PRI277). --> true - + TabularControlsAlias TabularControlsAlias true diff --git a/controls/dev/inc/BuildMacros.h b/controls/dev/inc/BuildMacros.h index 898cbf7628..2cc96394db 100644 --- a/controls/dev/inc/BuildMacros.h +++ b/controls/dev/inc/BuildMacros.h @@ -14,5 +14,3 @@ // Tabular ships its own resource map, so its theme resources are addressed under this root // rather than MUXC's; sharing MUXC's root caused a PRI277 collision. #define MUXTABULARROOT_NAMESPACE_STR L"Microsoft.UI.Xaml.Controls.Tabular" -// Resource-map alias: ms-appx authority so lookups bind to this component, not the host process. -#define MUXTABULARALIAS_STR L"TabularControlsAlias" From d7a7714ba1878973666318247dcd413260f98ada Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 18:11:59 +0530 Subject: [PATCH 12/31] Tabular: drop the vestigial PRI alias properties and scrub an internal bug ID XamlResourceMapName and ProjectPriIndexName named the standalone PRI's root map "TabularControlsAlias". Nothing consumes that name: the control resolves its default style through an authority-less ms-appx:/// URI, and a consuming app's build re-indexes the component PRI into its own resources.pri, discarding component root map names entirely. Verified rather than assumed. With both properties removed the emitted theme XBFs are byte-identical (all five SHA-256 hashes match) and the only PRI difference is the root map name, which falls back to the target name; the resource paths the runtime URI depends on are unchanged. MUXC sets neither property and its root map is "Microsoft.UI.Xaml", so defaulting is also the WinUI-consistent shape. AppxPriInitialPath and AppxPrependPriInitialPath stay -- those are load-bearing, since they place the XBFs at the path the default-style URI resolves. Comment added saying so, because this is the pair that actually matters. Also drops an internal bug ID from a pch.h comment. This repo mirrors publicly and comments mirror verbatim; the technical note is kept, the identifier is not. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Microsoft.UI.Xaml.Controls.Tabular.vcxproj | 12 +++++------- controls/dev/dll-tabular/pch.h | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj index 409bfeae05..a978c1a7c5 100644 --- a/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj +++ b/controls/dev/dll-tabular/Microsoft.UI.Xaml.Controls.Tabular.vcxproj @@ -21,13 +21,11 @@ (ms-appx:///Microsoft.UI.Xaml.Controls.Tabular/Themes/...). Without this they collide with MUXC's Microsoft.UI.Xaml root on merge (PRI277). --> true - - TabularControlsAlias - TabularControlsAlias + true $(MUXTabularTargetName) diff --git a/controls/dev/dll-tabular/pch.h b/controls/dev/dll-tabular/pch.h index 5e18b17c19..9f3cbad0af 100644 --- a/controls/dev/dll-tabular/pch.h +++ b/controls/dev/dll-tabular/pch.h @@ -12,7 +12,7 @@ // This bloats the file size of MUXC.dll by 50%, so we turn this C++/WinRT feature off. #define WINRT_NO_SOURCE_LOCATION -#pragma warning(disable : 6221) // Disable implicit cast warning for C++/WinRT headers (tracked by Bug 17528784: C++/WinRT headers trigger C6221 comparing e.code() to int-typed things) +#pragma warning(disable : 6221) // C++/WinRT headers trigger C6221 comparing e.code() to int-typed things. // Disable factory caching in CppWinRT as the global COM pointers that are released during dll/process // unload are not safe. Setting this makes CppWinRT just call get_activation_factory directly every time. From bf9c1bbd8faf0f879b51b83acb7708953f7a22fc Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 18:12:16 +0530 Subject: [PATCH 13/31] TableViewSampleApp: remove the last mock-era leftovers Four source files aliased every Tabular type, each with a comment saying the alias existed to "disambiguate the real split-binary type from the stale mock projection". That mock projection is gone, so the claim was tested rather than trusted: replacing an alias with a plain namespace import compiles with no CS0104. Microsoft.UI.Xaml.Controls and Microsoft.UI.Xaml.Controls.Tabular now coexist in the same file with no ambiguity, so there is no collision to disambiguate. Aliases replaced with a namespace import and the comments deleted. App.xaml no longer merges TabularControlsResources. Verified by removing it: all eight column headers and the rows still render, because the control resolves its own theme resources. The earlier belief that consumers must merge it came from changing two things at once -- adding the dictionary and declaring columns in the same step. It was the columns that mattered. Both docs corrected; they had been instructing readers to merge a dictionary they do not need. Also drops "Real" from a Playground label that distinguished the control from a mock that no longer exists. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Samples/TableViewSampleApp/AGENTS.md | 9 ++++-- Samples/TableViewSampleApp/App.xaml | 3 -- .../InteractiveCellsPage.xaml.cs | 3 +- .../TableViewSampleApp/PlaygroundPage.xaml | 2 +- .../TableViewSampleApp/PlaygroundPage.xaml.cs | 10 +----- Samples/TableViewSampleApp/README.md | 32 ++++++++----------- Samples/TableViewSampleApp/SampleColumns.cs | 5 +-- .../TableViewSampleApp/SelectionPage.xaml.cs | 4 +-- 8 files changed, 24 insertions(+), 44 deletions(-) diff --git a/Samples/TableViewSampleApp/AGENTS.md b/Samples/TableViewSampleApp/AGENTS.md index 4430209d25..3136d55628 100644 --- a/Samples/TableViewSampleApp/AGENTS.md +++ b/Samples/TableViewSampleApp/AGENTS.md @@ -46,9 +46,12 @@ sample's. ## Two things worth knowing -**Merge `TabularControlsResources`.** `App.xaml` merges it next to `XamlControlsResources`. The -control finds its own `generic.xaml` unaided, so without this the table still renders — but the -column header row and the theme brushes are missing, which looks like a control bug and is not one. +**Nothing needs merging.** The control resolves its own `generic.xaml` and theme resources from the +package, so `App.xaml` merges only `XamlControlsResources`. Verified by removing every Tabular +dictionary from this sample and confirming all eight column headers and the rows still render, and +again by the `TableViewApp` matrix (C#/C++ x packaged/unpackaged), none of which merge anything +Tabular-specific. If a table appears with no header row, the cause is almost always **no declared +columns**, not a missing dictionary. **`TableView` is `[MUX_PREVIEW]`.** C# usage raises `CS8305`, suppressed via `NoWarn` in the project file. XAML usage raises `WMC1501` once per page; those are deliberately left visible. diff --git a/Samples/TableViewSampleApp/App.xaml b/Samples/TableViewSampleApp/App.xaml index 7823a0e728..6bdcdb8338 100644 --- a/Samples/TableViewSampleApp/App.xaml +++ b/Samples/TableViewSampleApp/App.xaml @@ -8,9 +8,6 @@ - - diff --git a/Samples/TableViewSampleApp/InteractiveCellsPage.xaml.cs b/Samples/TableViewSampleApp/InteractiveCellsPage.xaml.cs index 3326bc2dcf..f9513d0cf9 100644 --- a/Samples/TableViewSampleApp/InteractiveCellsPage.xaml.cs +++ b/Samples/TableViewSampleApp/InteractiveCellsPage.xaml.cs @@ -1,8 +1,7 @@ using System.Collections.Generic; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -// Disambiguate the real split-binary column type from the stale mock projection. -using TableViewColumn = Microsoft.UI.Xaml.Controls.Tabular.TableViewColumn; +using Microsoft.UI.Xaml.Controls.Tabular; namespace TableViewSampleApp; diff --git a/Samples/TableViewSampleApp/PlaygroundPage.xaml b/Samples/TableViewSampleApp/PlaygroundPage.xaml index 08bb4aeb5d..59892bc357 100644 --- a/Samples/TableViewSampleApp/PlaygroundPage.xaml +++ b/Samples/TableViewSampleApp/PlaygroundPage.xaml @@ -16,7 +16,7 @@ + Text="Columns: Name (Text/Auto), Role & City (Text/*), Score (Template/120px). Tweak any control below to exercise the API live."/> diff --git a/Samples/TableViewSampleApp/PlaygroundPage.xaml.cs b/Samples/TableViewSampleApp/PlaygroundPage.xaml.cs index dcd75f64d5..eeaf6a4f53 100644 --- a/Samples/TableViewSampleApp/PlaygroundPage.xaml.cs +++ b/Samples/TableViewSampleApp/PlaygroundPage.xaml.cs @@ -5,18 +5,10 @@ using Microsoft.UI.Xaml.Media; using Windows.UI; using Microsoft.UI.Xaml.Controls.Tabular; -// Disambiguate the real split-binary control types from the stale mock projection -// (Microsoft.UI.Xaml.Controls.TableView*) that the mock Microsoft.WinUI.dll still carries. -using TableViewTextColumn = Microsoft.UI.Xaml.Controls.Tabular.TableViewTextColumn; -using TableViewTemplateColumn = Microsoft.UI.Xaml.Controls.Tabular.TableViewTemplateColumn; -using TableViewHeadersVisibility = Microsoft.UI.Xaml.Controls.Tabular.TableViewHeadersVisibility; -using TableViewGridLinesVisibility = Microsoft.UI.Xaml.Controls.Tabular.TableViewGridLinesVisibility; -using TableViewDensity = Microsoft.UI.Xaml.Controls.Tabular.TableViewDensity; -using TableViewFrozenEdge = Microsoft.UI.Xaml.Controls.Tabular.TableViewFrozenEdge; namespace TableViewSampleApp; -// Interactive playground: builds a TableView (real split-binary control) with one column of each +// Interactive playground: builds a TableView (control) with one column of each // kind, then wires the left panel so every public API can be exercised live. Data lives in Data.cs. public sealed partial class PlaygroundPage : Page { diff --git a/Samples/TableViewSampleApp/README.md b/Samples/TableViewSampleApp/README.md index 5ea1931144..b584728f94 100644 --- a/Samples/TableViewSampleApp/README.md +++ b/Samples/TableViewSampleApp/README.md @@ -43,25 +43,19 @@ BuildOutput\obj\amd64chk\Samples\TableViewSampleApp\TableViewSampleApp.exe ## Using TableView in your own app -Two things, both ordinary: - -1. Reference `Microsoft.WindowsAppSDK.WinUI`. -2. Merge the control's theme dictionary alongside `XamlControlsResources`, so its brushes and - metrics are in scope: - - ```xml - - - - - - - - - ``` - - Without the second dictionary the control still gets its template, but the column header row and - the theme brushes will be missing. +Reference `Microsoft.WindowsAppSDK.WinUI` and use the control. Nothing else — the control resolves +its own default style and theme resources from the package, so there is no dictionary to merge and +no URI to configure. The `TableViewApp` samples alongside this one demonstrate that in all four +consumer shapes (C# and C++, packaged and unpackaged). + +Declare columns, or the table renders rows with no header row and no cells: + +```xml + + + + +``` `TableView` is `[MUX_PREVIEW]`, so C# usage raises `CS8305` and XAML usage raises `WMC1501` ("for evaluation purposes only"). This sample suppresses `CS8305`; the XAML warnings are left diff --git a/Samples/TableViewSampleApp/SampleColumns.cs b/Samples/TableViewSampleApp/SampleColumns.cs index ace1affc3f..4458b0d7e7 100644 --- a/Samples/TableViewSampleApp/SampleColumns.cs +++ b/Samples/TableViewSampleApp/SampleColumns.cs @@ -1,9 +1,6 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Data; -// Disambiguate the real split-binary column types from the stale mock projection -// (Microsoft.UI.Xaml.Controls.TableView*) that the mock Microsoft.WinUI.dll still carries. -using TableViewTextColumn = Microsoft.UI.Xaml.Controls.Tabular.TableViewTextColumn; -using TableViewTemplateColumn = Microsoft.UI.Xaml.Controls.Tabular.TableViewTemplateColumn; +using Microsoft.UI.Xaml.Controls.Tabular; namespace TableViewSampleApp; diff --git a/Samples/TableViewSampleApp/SelectionPage.xaml.cs b/Samples/TableViewSampleApp/SelectionPage.xaml.cs index 7b57c30902..3d9a4246f0 100644 --- a/Samples/TableViewSampleApp/SelectionPage.xaml.cs +++ b/Samples/TableViewSampleApp/SelectionPage.xaml.cs @@ -2,9 +2,7 @@ using System.Linq; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -// Disambiguate the real split-binary types from the stale mock projection. -using TableView = Microsoft.UI.Xaml.Controls.Tabular.TableView; -using TableViewSelectionMode = Microsoft.UI.Xaml.Controls.Tabular.TableViewSelectionMode; +using Microsoft.UI.Xaml.Controls.Tabular; namespace TableViewSampleApp; From d73db1425d12d61f66f53ec06815384c0d9a7aaf Mon Sep 17 00:00:00 2001 From: Hitesh Kumar Date: Wed, 26 Aug 2026 18:12:52 +0530 Subject: [PATCH 14/31] Samples: add a TableView consumer matrix for C#/C++ x packaged/unpackaged Four minimal apps that consume TableView the way a customer would, modelled on the ChartApp samples, which are the existing pattern in this repo for a separately-built control set. Each references Microsoft.WindowsAppSDK.WinUI and nothing else, and App.xaml merges only XamlControlsResources: no projection regeneration, no manifest injection, no theme resources compiled from the control source, no staged DLL, no type seed, and no project reference into the control. Each app instantiates TableView twice on purpose. One comes from markup, exercising XamlTypeInfo and XAML-driven activation; the other is built in code-behind, exercising direct WinRT activation. Those paths fail independently, and the defect this matrix guards against was an activation and default-style failure, so both are covered. The C# apps bind with a classic {Binding} against a plain class. The C++ apps use TableViewTemplateColumn with x:Bind against a Person runtimeclass. That asymmetry is a C++/WinRT rule, not a control limitation: classic {Binding} resolves properties by reflection in .NET, but C++/WinRT needs an IXamlType, which the XAML compiler emits only for types it sees in markup, or an explicit ICustomPropertyProvider. A data type built purely from code has neither, so {Binding} silently resolves nothing and cells render empty while headers, rows, grid lines and theming all look correct. The README records this so the next person does not read it as a control bug. Preview-API warnings are left visible here, unlike TableViewSampleApp which suppresses CS8305 because it fires 324 times across the full API surface. The README states that split so it reads as a choice. All four build clean and run; the C# pair and the C++ packaged app were confirmed rendering bound data in both their tables. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Samples/TableViewApp/README.md | 68 ++++++ Samples/TableViewApp/TableViewApp.sln | 135 +++++++++++ .../TableViewAppCppPackaged/App.xaml | 14 ++ .../TableViewAppCppPackaged/App.xaml.cpp | 29 +++ .../TableViewAppCppPackaged/App.xaml.h | 16 ++ .../Assets/LockScreenLogo.scale-200.png | Bin 0 -> 432 bytes .../Assets/SplashScreen.scale-200.png | Bin 0 -> 5372 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 1755 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 0 -> 637 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 283 bytes .../Assets/StoreLogo.png | Bin 0 -> 456 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 2097 bytes .../TableViewAppCppPackaged/MainWindow.idl | 17 ++ .../TableViewAppCppPackaged/MainWindow.xaml | 55 +++++ .../MainWindow.xaml.cpp | 59 +++++ .../TableViewAppCppPackaged/MainWindow.xaml.h | 27 +++ .../Package.appxmanifest | 51 ++++ .../TableViewAppCppPackaged/Person.cpp | 3 + .../TableViewAppCppPackaged/Person.h | 30 +++ .../TableViewAppCppPackaged.vcxproj | 225 ++++++++++++++++++ .../TableViewAppCppPackaged/app.manifest | 16 ++ .../TableViewAppCppPackaged/packages.config | 7 + .../TableViewAppCppPackaged/pch.cpp | 1 + .../TableViewAppCppPackaged/pch.h | 23 ++ .../TableViewAppCppUnpackaged/App.xaml | 14 ++ .../TableViewAppCppUnpackaged/App.xaml.cpp | 29 +++ .../TableViewAppCppUnpackaged/App.xaml.h | 16 ++ .../Assets/LockScreenLogo.scale-200.png | Bin 0 -> 432 bytes .../Assets/SplashScreen.scale-200.png | Bin 0 -> 5372 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 1755 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 0 -> 637 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 283 bytes .../Assets/StoreLogo.png | Bin 0 -> 456 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 2097 bytes .../TableViewAppCppUnpackaged/MainWindow.idl | 17 ++ .../TableViewAppCppUnpackaged/MainWindow.xaml | 55 +++++ .../MainWindow.xaml.cpp | 59 +++++ .../MainWindow.xaml.h | 27 +++ .../TableViewAppCppUnpackaged/Person.cpp | 3 + .../TableViewAppCppUnpackaged/Person.h | 30 +++ .../TableViewAppCppUnpackaged.vcxproj | 218 +++++++++++++++++ .../TableViewAppCppUnpackaged/app.manifest | 16 ++ .../TableViewAppCppUnpackaged/packages.config | 7 + .../TableViewAppCppUnpackaged/pch.cpp | 1 + .../TableViewAppCppUnpackaged/pch.h | 23 ++ .../TableViewAppCsPackaged/App.xaml | 16 ++ .../TableViewAppCsPackaged/App.xaml.cs | 20 ++ .../Assets/LockScreenLogo.scale-200.png | Bin 0 -> 432 bytes .../Assets/SplashScreen.scale-200.png | Bin 0 -> 5372 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 1755 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 0 -> 637 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 283 bytes .../Assets/StoreLogo.png | Bin 0 -> 456 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 2097 bytes .../TableViewAppCsPackaged/MainWindow.xaml | 43 ++++ .../TableViewAppCsPackaged/MainWindow.xaml.cs | 52 ++++ .../Package.appxmanifest | 50 ++++ .../PublishProfiles/win-arm64.pubxml | 17 ++ .../PublishProfiles/win-arm64ec.pubxml | 17 ++ .../Properties/PublishProfiles/win-x64.pubxml | 17 ++ .../Properties/PublishProfiles/win-x86.pubxml | 17 ++ .../TableViewAppCsPackaged.csproj | 44 ++++ .../TableViewAppCsPackaged/app.manifest | 11 + .../TableViewAppCsUnpackaged/App.xaml | 16 ++ .../TableViewAppCsUnpackaged/App.xaml.cs | 20 ++ .../Assets/LockScreenLogo.scale-200.png | Bin 0 -> 432 bytes .../Assets/SplashScreen.scale-200.png | Bin 0 -> 5372 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 1755 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 0 -> 637 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 283 bytes .../Assets/StoreLogo.png | Bin 0 -> 456 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 2097 bytes .../TableViewAppCsUnpackaged/MainWindow.xaml | 43 ++++ .../MainWindow.xaml.cs | 52 ++++ .../PublishProfiles/win-arm64.pubxml | 19 ++ .../PublishProfiles/win-arm64ec.pubxml | 19 ++ .../Properties/PublishProfiles/win-x64.pubxml | 19 ++ .../Properties/PublishProfiles/win-x86.pubxml | 19 ++ .../TableViewAppCsUnpackaged.csproj | 34 +++ .../TableViewAppCsUnpackaged/app.manifest | 11 + 80 files changed, 1847 insertions(+) create mode 100644 Samples/TableViewApp/README.md create mode 100644 Samples/TableViewApp/TableViewApp.sln create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/App.xaml create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/App.xaml.cpp create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/App.xaml.h create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/Assets/LockScreenLogo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/Assets/SplashScreen.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/Assets/Square150x150Logo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/Assets/Square44x44Logo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/Assets/StoreLogo.png create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/Assets/Wide310x150Logo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/MainWindow.idl create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/MainWindow.xaml create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/MainWindow.xaml.cpp create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/MainWindow.xaml.h create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/Package.appxmanifest create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/Person.cpp create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/Person.h create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/TableViewAppCppPackaged.vcxproj create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/app.manifest create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/packages.config create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/pch.cpp create mode 100644 Samples/TableViewApp/TableViewAppCppPackaged/pch.h create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/App.xaml create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/App.xaml.cpp create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/App.xaml.h create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/Assets/LockScreenLogo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/Assets/SplashScreen.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/Assets/Square150x150Logo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/Assets/Square44x44Logo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/Assets/StoreLogo.png create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/Assets/Wide310x150Logo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/MainWindow.idl create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/MainWindow.xaml create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/MainWindow.xaml.cpp create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/MainWindow.xaml.h create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/Person.cpp create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/Person.h create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/TableViewAppCppUnpackaged.vcxproj create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/app.manifest create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/packages.config create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/pch.cpp create mode 100644 Samples/TableViewApp/TableViewAppCppUnpackaged/pch.h create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/App.xaml create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/App.xaml.cs create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/Assets/LockScreenLogo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/Assets/SplashScreen.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/Assets/Square150x150Logo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/Assets/Square44x44Logo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/Assets/StoreLogo.png create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/Assets/Wide310x150Logo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/MainWindow.xaml create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/MainWindow.xaml.cs create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/Package.appxmanifest create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/Properties/PublishProfiles/win-arm64.pubxml create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/Properties/PublishProfiles/win-arm64ec.pubxml create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/Properties/PublishProfiles/win-x64.pubxml create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/Properties/PublishProfiles/win-x86.pubxml create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/TableViewAppCsPackaged.csproj create mode 100644 Samples/TableViewApp/TableViewAppCsPackaged/app.manifest create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/App.xaml create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/App.xaml.cs create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/Assets/LockScreenLogo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/Assets/SplashScreen.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/Assets/Square150x150Logo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/Assets/Square44x44Logo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/Assets/StoreLogo.png create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/Assets/Wide310x150Logo.scale-200.png create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/MainWindow.xaml create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/MainWindow.xaml.cs create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/Properties/PublishProfiles/win-arm64.pubxml create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/Properties/PublishProfiles/win-arm64ec.pubxml create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/Properties/PublishProfiles/win-x64.pubxml create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/Properties/PublishProfiles/win-x86.pubxml create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/TableViewAppCsUnpackaged.csproj create mode 100644 Samples/TableViewApp/TableViewAppCsUnpackaged/app.manifest diff --git a/Samples/TableViewApp/README.md b/Samples/TableViewApp/README.md new file mode 100644 index 0000000000..94a579e742 --- /dev/null +++ b/Samples/TableViewApp/README.md @@ -0,0 +1,68 @@ +# TableView consumer matrix + +Four minimal apps that consume `TableView` the way a real customer would — **C# and C++, packaged and +unpackaged** — to prove the control works in every host shape without app-side workarounds. + +| | Packaged | Unpackaged | +|---|---|---| +| **C#** | `TableViewAppCsPackaged` | `TableViewAppCsUnpackaged` | +| **C++** | `TableViewAppCppPackaged` | `TableViewAppCppUnpackaged` | + +Modelled on the [ChartApp](../ChartApp) samples, which are the existing pattern in this repo for a +separately-built control set. + +## What they prove + +Each app references `Microsoft.WindowsAppSDK.WinUI` **and nothing else**. `App.xaml` merges only +`XamlControlsResources`, exactly as ChartApp does. There is no projection regeneration, no manifest +injection, no theme resources compiled from the control source, no staged DLL, and no type seed — +the control resolves its own default style and theme resources from the package. + +Each app instantiates `TableView` **twice on purpose**: + +- once from **markup**, which exercises XamlTypeInfo, the metadata provider and XAML-driven activation; +- once from **code-behind**, which exercises direct WinRT activation with no markup involved. + +Those are separate paths and either can fail alone, so a conformance check wants both. + +## Build and run + +``` +.\initrun.ps1 msb /restore Samples\TableViewApp\TableViewAppCsPackaged\TableViewAppCsPackaged.csproj /p:Platform=x64 +``` + +To test a locally built control, pack the component and override the version: + +``` +.\pack.component.cmd /version 3.0.0-mylocal +... /p:WinUIVersion=3.0.0-mylocal +``` + +The unpackaged apps run straight from their output directory. The packaged apps produce a loose +layout; register it with `Add-AppxPackage -Register \AppxManifest.xml` and launch from Start. + +## Why the C# and C++ apps bind differently + +The C# apps use `TableViewTextColumn.Binding` with a classic `{Binding}` against a plain `Person` +class. The C++ apps use `TableViewTemplateColumn.CellTemplate` with `x:Bind` against a `Person` +runtimeclass declared in `MainWindow.idl`. + +That difference is a **C++/WinRT data-binding rule, not a control limitation**. Classic `{Binding}` +resolves properties through reflection in .NET, but C++/WinRT has no reflection: it needs an +`IXamlType`, which the XAML compiler emits only for types it encounters **in markup**, or an +explicit `ICustomPropertyProvider` implementation. A data type constructed purely from code has +neither, so `{Binding}` silently resolves nothing and every cell renders empty while headers, rows, +grid lines and theming all look perfectly correct. + +`x:Bind` compiles the property access at build time, needs no runtime type information, and is the +right default for a C++/WinRT consumer. + +## Preview-API warnings are left visible here + +`TableView` is `[MUX_PREVIEW]`, so C# usage raises `CS8305` and XAML usage raises `WMC1501` +("for evaluation purposes only"). These apps **do not** suppress them: they are small, the warning +count stays low, and a consumer reading a conformance sample should see that the API is preview. + +`TableViewSampleApp` takes the opposite choice deliberately — it exercises the whole API surface, so +un-suppressed `CS8305` fires 324 times and would bury every other warning. That difference is +intentional, not an oversight. diff --git a/Samples/TableViewApp/TableViewApp.sln b/Samples/TableViewApp/TableViewApp.sln new file mode 100644 index 0000000000..37afd9106b --- /dev/null +++ b/Samples/TableViewApp/TableViewApp.sln @@ -0,0 +1,135 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.37314.3 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TableViewAppCppUnpackaged", "TableViewAppCppUnpackaged\TableViewAppCppUnpackaged.vcxproj", "{050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TableViewAppCppPackaged", "TableViewAppCppPackaged\TableViewAppCppPackaged.vcxproj", "{1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TableViewAppCsUnpackaged", "TableViewAppCsUnpackaged\TableViewAppCsUnpackaged.csproj", "{F9AE50FC-FACF-4E88-8C05-27DF41902470}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TableViewAppCsPackaged", "TableViewAppCsPackaged\TableViewAppCsPackaged.csproj", "{B43A3294-ED51-4784-9957-E7D033330B05}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|ARM64EC = Debug|ARM64EC + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 + Release|ARM64EC = Release|ARM64EC + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Debug|ARM64.Build.0 = Debug|ARM64 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Debug|ARM64EC.Build.0 = Debug|ARM64EC + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Debug|Win32.ActiveCfg = Debug|Win32 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Debug|Win32.Build.0 = Debug|Win32 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Debug|x64.ActiveCfg = Debug|x64 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Debug|x64.Build.0 = Debug|x64 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Debug|x86.ActiveCfg = Debug|Win32 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Debug|x86.Build.0 = Debug|Win32 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Release|ARM64.ActiveCfg = Release|ARM64 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Release|ARM64.Build.0 = Release|ARM64 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Release|ARM64EC.Build.0 = Release|ARM64EC + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Release|Win32.ActiveCfg = Release|Win32 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Release|Win32.Build.0 = Release|Win32 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Release|x64.ActiveCfg = Release|x64 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Release|x64.Build.0 = Release|x64 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Release|x86.ActiveCfg = Release|Win32 + {050FC711-CCFB-4BB4-B771-D4C35E8D5FCE}.Release|x86.Build.0 = Release|Win32 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|ARM64.Build.0 = Debug|ARM64 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|ARM64EC.Build.0 = Debug|ARM64EC + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|ARM64EC.Deploy.0 = Debug|ARM64EC + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|Win32.ActiveCfg = Debug|Win32 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|Win32.Build.0 = Debug|Win32 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|Win32.Deploy.0 = Debug|Win32 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|x64.ActiveCfg = Debug|x64 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|x64.Build.0 = Debug|x64 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|x64.Deploy.0 = Debug|x64 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|x86.ActiveCfg = Debug|Win32 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|x86.Build.0 = Debug|Win32 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Debug|x86.Deploy.0 = Debug|Win32 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|ARM64.ActiveCfg = Release|ARM64 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|ARM64.Build.0 = Release|ARM64 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|ARM64.Deploy.0 = Release|ARM64 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|ARM64EC.Build.0 = Release|ARM64EC + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|ARM64EC.Deploy.0 = Release|ARM64EC + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|Win32.ActiveCfg = Release|Win32 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|Win32.Build.0 = Release|Win32 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|Win32.Deploy.0 = Release|Win32 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|x64.ActiveCfg = Release|x64 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|x64.Build.0 = Release|x64 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|x64.Deploy.0 = Release|x64 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|x86.ActiveCfg = Release|Win32 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|x86.Build.0 = Release|Win32 + {1930FFBA-85CD-4E12-BBF1-23CB28D47D4F}.Release|x86.Deploy.0 = Release|Win32 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Debug|ARM64.Build.0 = Debug|ARM64 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Debug|ARM64EC.Build.0 = Debug|ARM64EC + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Debug|Win32.ActiveCfg = Debug|x86 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Debug|Win32.Build.0 = Debug|x86 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Debug|x64.ActiveCfg = Debug|x64 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Debug|x64.Build.0 = Debug|x64 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Debug|x86.ActiveCfg = Debug|x86 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Debug|x86.Build.0 = Debug|x86 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Release|ARM64.ActiveCfg = Release|ARM64 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Release|ARM64.Build.0 = Release|ARM64 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Release|ARM64EC.Build.0 = Release|ARM64EC + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Release|Win32.ActiveCfg = Release|x86 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Release|Win32.Build.0 = Release|x86 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Release|x64.ActiveCfg = Release|x64 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Release|x64.Build.0 = Release|x64 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Release|x86.ActiveCfg = Release|x86 + {F9AE50FC-FACF-4E88-8C05-27DF41902470}.Release|x86.Build.0 = Release|x86 + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|ARM64.Build.0 = Debug|ARM64 + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|ARM64EC.Build.0 = Debug|ARM64EC + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|ARM64EC.Deploy.0 = Debug|ARM64EC + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|Win32.ActiveCfg = Debug|x86 + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|Win32.Build.0 = Debug|x86 + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|Win32.Deploy.0 = Debug|x86 + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|x64.ActiveCfg = Debug|x64 + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|x64.Build.0 = Debug|x64 + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|x64.Deploy.0 = Debug|x64 + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|x86.ActiveCfg = Debug|x86 + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|x86.Build.0 = Debug|x86 + {B43A3294-ED51-4784-9957-E7D033330B05}.Debug|x86.Deploy.0 = Debug|x86 + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|ARM64.ActiveCfg = Release|ARM64 + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|ARM64.Build.0 = Release|ARM64 + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|ARM64.Deploy.0 = Release|ARM64 + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|ARM64EC.Build.0 = Release|ARM64EC + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|ARM64EC.Deploy.0 = Release|ARM64EC + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|Win32.ActiveCfg = Release|x86 + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|Win32.Build.0 = Release|x86 + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|Win32.Deploy.0 = Release|x86 + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|x64.ActiveCfg = Release|x64 + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|x64.Build.0 = Release|x64 + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|x64.Deploy.0 = Release|x64 + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|x86.ActiveCfg = Release|x86 + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|x86.Build.0 = Release|x86 + {B43A3294-ED51-4784-9957-E7D033330B05}.Release|x86.Deploy.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {09593217-0E5B-4DFD-8DF3-16E5A2374FB9} + EndGlobalSection +EndGlobal diff --git a/Samples/TableViewApp/TableViewAppCppPackaged/App.xaml b/Samples/TableViewApp/TableViewAppCppPackaged/App.xaml new file mode 100644 index 0000000000..db72c86871 --- /dev/null +++ b/Samples/TableViewApp/TableViewAppCppPackaged/App.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/Samples/TableViewApp/TableViewAppCppPackaged/App.xaml.cpp b/Samples/TableViewApp/TableViewAppCppPackaged/App.xaml.cpp new file mode 100644 index 0000000000..83c3826d27 --- /dev/null +++ b/Samples/TableViewApp/TableViewAppCppPackaged/App.xaml.cpp @@ -0,0 +1,29 @@ +#include "pch.h" +#include "App.xaml.h" +#include "MainWindow.xaml.h" + +using namespace winrt; +using namespace Microsoft::UI::Xaml; + +namespace winrt::TableViewAppCppPackaged::implementation +{ + App::App() + { +#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION + UnhandledException([](IInspectable const&, UnhandledExceptionEventArgs const& e) + { + if (IsDebuggerPresent()) + { + auto errorMessage = e.Message(); + __debugbreak(); + } + }); +#endif + } + + void App::OnLaunched([[maybe_unused]] LaunchActivatedEventArgs const& e) + { + window = make(); + window.Activate(); + } +} diff --git a/Samples/TableViewApp/TableViewAppCppPackaged/App.xaml.h b/Samples/TableViewApp/TableViewAppCppPackaged/App.xaml.h new file mode 100644 index 0000000000..dd5e8d12bd --- /dev/null +++ b/Samples/TableViewApp/TableViewAppCppPackaged/App.xaml.h @@ -0,0 +1,16 @@ +#pragma once + +#include "App.xaml.g.h" + +namespace winrt::TableViewAppCppPackaged::implementation +{ + struct App : AppT + { + App(); + + void OnLaunched(Microsoft::UI::Xaml::LaunchActivatedEventArgs const&); + + private: + winrt::Microsoft::UI::Xaml::Window window{ nullptr }; + }; +} diff --git a/Samples/TableViewApp/TableViewAppCppPackaged/Assets/LockScreenLogo.scale-200.png b/Samples/TableViewApp/TableViewAppCppPackaged/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..7440f0d4bf7c7e26e4e36328738c68e624ee851e GIT binary patch literal 432 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezr3(FqV6|IEGZ*x-#9g>~Mkr+x6^F zy~CDX2QIMs&Gcs3RnRBoxBA!*(Mfw0KTCYuYk0WlEIV>qBmPl! zq4ukrvfADX@#p8fbLY(H47N+k`FZ(FZh?cDro7>{8mkBO3>^oaIx`3!Jl)Qq)HI!+ z(S=1{o~eT)&W^=Ea8C`-17(Jv5(nHFJ{dOjGdxLVkY_y6&S1whfuFI4MM0kF0f&cO zPDVpV%nz;Id$>+0Ga5e9625-JcI)oq=#Pa3p^>8BB}21BUw@eN!-6@w%X+^`+Vn?! zryu|3T>kVWNBYyBc=7Y6H#s1Ah!OI_nezW zXTqOdkv2Az6KKBV=$yHdF^R3Fqw(TZEoNSZX>reXJ#bwX42%f|Pgg&ebxsLQ010xn AssI20 literal 0 HcmV?d00001 diff --git a/Samples/TableViewApp/TableViewAppCppPackaged/Assets/SplashScreen.scale-200.png b/Samples/TableViewApp/TableViewAppCppPackaged/Assets/SplashScreen.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..32f486a86792a5e34cd9a8261b394c49b48f86be GIT binary patch literal 5372 zcmd5=Z){Ul6u)iv53sCbIJKLzl(EF%0tzcEY@|pLrfgF~2Dk$KFtU+$kbYqDN5W%7 z>?DBo!@y06eh{Oux>brrNT^{MO(tkiC@nH(2}}G_1|uvcMD(0{?|W^Gxo!tG~hW2Rn&7%b`-Kd_^`BCrb>XVtRKONoEw6%NswzMxk+kbocuk&}kJ#hSP z>8uR{r%LJ?I#)aaWW;uEixz+DzyTpp)MTEo&R%nEA92~g{^eXQwKV1m{xl5K<@k3FacT+Z zrwfy=VocIptI>t%@p5a;Rt=WXVnU;2SUdr7Yk>gw_2z_ICK^23$|Cg7{3Eg5j@N*F zetT?>30(*S_7ld-Yt&u7T{(hEjjM#vPlXibjrq?;pBBx3*>_2~VFGdsH5L zQKme_LAebV}aOX#+rQafZtp+4jK}V!>pn1?+eUH$0%6}z(Kul9!^2z zXi+d@jnx)RW7!j9uFEdv5N&1sCW#Z6Ej5Y7c;o28Q7i%U0(2v5J>o9P zl$#C8&9r)nL;?J65^GIeSOHYr3B7}}R~}@2Tx_xo5*YdU#g1bO}95cq69J!efdlE+xj1qG#ZUqh~1Sn#dBsZfDvcupM zXOFoyJ0$s+RHQKpzr#T>c&EUbq)lGvZDxuI!9unMI=#;ob2&gT)WqOjt6^X`_N21r`&eh6h0xpT!n6Z9rvE&+bFU$vTJO2? z#^tBNOx*2N)~(+TH8d>ep6``8V=3JEfdUUahVZ-xN+k#V&32x|%qnX(XBii5<@`%^ zV#Ky4f1!6RJqJXBU3M4~tmj2;;r`8_j&w?h5g35uMH(QI$Xpesb zG|*XRT?kh6M(jj0Y&vF^M*9g-iDMW%G%9%Pa}6ERQ9b0%6z1v}Ja=|L@G#5ZI>JS9 z*(K12nMvS?oyG8s9|q~{w`ajtI`KSHSiJ;)%X@M&eCE(VqI#F(XL?L@A$TUT?6av5 zkPWIR391XjSC%d6L}7F71Qpw(;c_~)mSZo-&Fm^FHlPX|Fu}1B3E+9j0}o1a(4HFS zUItE22CC%XZi!b4%~vWn>rpV9&CUEvt!?Q{Pr*L~51&(0Sz{VJJFrJtWw2PwXd|J{ zgH%3vAY$flodH=4&ruCHX;(3t;o}n?!0~3EE|5qRz$!VIkphxa4@_jyfiE9m;0 zjcYJ2;26N&MTB8X4joZ&?SUe|VS$^I%dt{!c2O;%3SdqW@K_14r8eyC1s&VcU5+2~ z_O1Cc*w|aIA=VC6AT_EFoL}W#Rl;7CZe)e}RS*e;8CVyM6i8a(yO@|S709VYY(y2g zc+QxB>Bw^B^2Db~*o)=i$m-aUNQFkYy5(eJW$cez>C{POds*p3cy#tHnvActP;dBP zdEf)C;lq}&#PE?XCD<~ngrzYUg|nS`#MS`Rd7cT>xlR19P#~4Qg5!J}@glCUq)z_2 zjvyv%aSq0 z)njao1dV0XNw&c@qmj1e*jgQ$l@_urW5G4RSY#rT1z`#%3;{EB`aJK|TH^lb_3nAT z-_Q4X-(K&IS8UyqsnjYdippfmN-HT!X2MT;Dpcy~-#$k6V z|MR4vU#O&p7TC46pTflb3 zoUJ;ZRf#&8&EwXy5s%!&(q6cN62swD#FH%O-RJsjWPZN3^^@FCIQ&MxXIFo7!I#VI zkpIstuWqUV5uhgs07?k$*!`uiZ=5b#$lI|0c+XJvj(}zSE3MN#EyOK zql(#yA}~Ibl*r(s1}Z^5mmn*-n93g?-ccM+^PN?6HH~h0hjy6@XY*^i<-V)+OZ;p7 z7j`p_sT55xnYsedNIIel^QIIg7i@`2Qi}x5$!tk29$2OQI zs^kQXAKE}5ZJu$)2@Dxn?}}O@f@6@^!%9Tj+o>=jd!^ZuvBE4jb4g}Z5WMBtcmy^~ zoFGVS5|0FA!(1Q%fL?Bj*L+9ZL{mjSO8lzqrQ0UCZ)X zPwk$1HNFgaK%NxGpuXz}#ywXvf2JQ?BQ5uOZM2up4S#ieaxS$!o9o6Z=czNQb} zwAh|xLZ>+WyN%o?^uCAQw&&4o?S$DJ`WP(Hr*grL*qNXlqU0osCQ(Up5F(^$Z5;n&oJIO4uF`k&QL*j{f zU=;#MZ5{@b%qMbjTB3dh-5#mqY>%{0jgS+WdHyG literal 0 HcmV?d00001 diff --git a/Samples/TableViewApp/TableViewAppCppPackaged/Assets/Square44x44Logo.scale-200.png b/Samples/TableViewApp/TableViewAppCppPackaged/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..f713bba67f551ef91020b75716a4dc8ebd744b1c GIT binary patch literal 637 zcmeAS@N?(olHy`uVBq!ia0vp^5g^RL1|$oo8kjIJFu8cTIEGZ*dUI*J;2{SImxtDO zm%3!R$UazoY}x{$j0P5ABYXWr(l=jxJ6ps1W{tV=^>{Dl><3nv3A}sm=EZ)#l3`NR zpZda3^rNox*D1%NC98Z~L*6zipLw~Gxn&(Y-;KmJ+aR6eLabU-L#y8HW%7P-E_-VlLqIabbHPHKT*)fT@9iWJ7iWgOT9%0}Lrj>lztPxWq6sPw3pi z#-<=#$jjrP_DD*i!RLsn0mIA=>4~N)IMYWIf=j%-zuKCdMG%tHYot70D1| zvWa0wMhauW#S>1CnI_;>!1Q3zMA17@DOVq{MQ+{U7^a&yA+%dMCG;WNPV0i;w$tu; zX^b}UKziPM)(<;)ruW;-`)bBN+rQNM*Zs_>?n$|FVFo-e*PZb*@U7VAd+tHb4e?=Blc~}S6K)wL}r*Gf`BM#QB z+y>N$mCswb4d{^{S9v_!eQj4fTRMOwOCi?lSk9%<=vAz}jM-*PQtH@Odn1LZcd^j#o> hW$4xn+CT+ep9lJ{OAO?njobhL002ovPDHLkV1nYebbkN< literal 0 HcmV?d00001 diff --git a/Samples/TableViewApp/TableViewAppCppPackaged/Assets/StoreLogo.png b/Samples/TableViewApp/TableViewAppCppPackaged/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..a4586f26bdf7841cad10f39cdffe2aca3af252c1 GIT binary patch literal 456 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2o;fF!p=8IEGZ*dUM0H=rDtTTVkd2 z(%lbKn@VS_lUaADVB&;Z6F#LM+mPsa?e>FnHo;HND^!P`-lX%BH~FOg%y&x+t*x!? zg$#_1A1kgsSvO(fw`bOmo;lrJX8byO1j^gf7qohR%mmt z@L)WX;>gqgK|tWJvQ5j;4;=gt4HXVKSMYRv5RhY5vS~TqfK_NAP*r{h!!g^BZ;w4r z7CGdsai)y;fJQc`7{Zc2b==h%o`Op$|bg6a&nL{*m7-=0>k4M4-PXlU;G-?%*(*g>iFt^ U$m#7DfHB12>FVdQ&MBb@0G`#n8vpc0sq%A~kJcD9FY~qQRMt?ZR3YyDZt}Od;|mgpc{2dv9AHF){kXU%k({ z=Y8JidEayHTkG@twPZ|U3_^%3ct-OgLSiFAqDN!|tbCX@c@?4P`2x*TMK!+Q4b?k0 ziW7!!KF6dPWcF<%I|iznM~`QJ_V7sHGV_D`dhgpA9Vd@&X}ErK+j~_rdv;Bp?OA@a zFXOk7eWOJe5NcK;6h$FaM&7JxNc#-@QTwzW6x#d_zmQNkz5) zPI;kh;3d;5UCJU+9a(cOxX(|edWoOiAEdGU#kPJ&xnc2||3vDbuhBCkj-pb0as$Zl z5;}4n=**n6(1g`JEtSy;SG6X;#-F~Oz3lESG2b5`j@wAwY4Yp<=4Xeb>iH=6aicF?DxD&q{`!&}ct zBI)aycwuobQAf&678Uf+Mmh-@9RUhyH~>?w0dixO0#jZjEc9R^=5NZw=|a(kcB?9^ zfnTiEFXp-q#B;Tn>(O%$A*ud^Rg&eVH6Y_5Y%!E39RR&s?XpG`gKwU!6FE1 z7X)DC7)*(5g}lh`4`{i~DZcWupZI`K)_4P)VE{@gc7@Xsd^86zl~_mOYH?I4!aGeX z^E(_=L6?PgveDQ+r%P@UISEXrkn`LHJZ##+!-anV>6h)IkKp;E@p8+3&(5%kS2)ld*J*rJccZM0iyaAx7+F~GW1UWFK&3X$PE1^}NH zgAG9ck5K!{07OwU@j@Do>TbH=CDEo#4m0cEyAuXy_<&jlzJVcKweSJ5 z&=q~iIn18$w8yb=rmEmHxVEUA^?RwnB?6Qlp1os8@*dWTGL2bhzZ!s*xqScR?EPL` zo(JwNdKUUYy7GtvZ3asXm)cgFvCx9EmAi;|w=a0iGiv%%VYKh`P0Wma4y`Xyx|T~( zAmfGbgbEEC7)j8b@WA@+5W3a61HJXC1dX@6_T|Czk0I0zBk%tnW~()VWITGI!`$c< gARL?UBrYYkwoDw4eo*CrzXGTrZ@;GF>596)00d&n@&Et; literal 0 HcmV?d00001 diff --git a/Samples/TableViewApp/TableViewAppCppPackaged/MainWindow.idl b/Samples/TableViewApp/TableViewAppCppPackaged/MainWindow.idl new file mode 100644 index 0000000000..cce396d2e5 --- /dev/null +++ b/Samples/TableViewApp/TableViewAppCppPackaged/MainWindow.idl @@ -0,0 +1,17 @@ +namespace TableViewAppCppPackaged +{ + [default_interface] + runtimeclass Person + { + Person(); + String Name; + Int32 Age; + String AgeText{ get; }; + } + + [default_interface] + runtimeclass MainWindow : Microsoft.UI.Xaml.Window + { + MainWindow(); + } +} \ No newline at end of file diff --git a/Samples/TableViewApp/TableViewAppCppPackaged/MainWindow.xaml b/Samples/TableViewApp/TableViewAppCppPackaged/MainWindow.xaml new file mode 100644 index 0000000000..4d1355e253 --- /dev/null +++ b/Samples/TableViewApp/TableViewAppCppPackaged/MainWindow.xaml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + +