使用 Visual Studio 2022、C#、WPF、.NET Framework 4.7.2 项目。
有什么方法可以在构建时选择 XAML 文件,例如基于构建配置或编译符号,或其他任何东西?
用例:我现在成熟的产品被设计为在 2K 横向屏幕上运行,所有 UI 布局都是在 XAML 中完成的,并且它会自动调整到屏幕尺寸到合理的程度。然而,我刚刚被要求制作一个在 800x1200 纵向屏幕上运行的版本。因此,我将不得不完全重新设计屏幕的布局,但它将具有所有相同的对象和功能。布局变化如此剧烈,UI 如此复杂,只有选择完全不同的 XMAL 才有意义。我在第二篇文章中使用了这个想法,基本上将我的 XAML 文件切成两半,复制/粘贴到后半部分并更改布局,但因为这是运行时检查,所以在编译时我得到了无数的“ xyz 已定义...”由于具有相同名称的重复对象,所以不幸的是它不适用于我的情况。除了使用新的 XAML 文件创建全新的 Visual Studio 项目但与原始项目共享 .cs 文件之外,还有其他想法吗?
ResourceManager
、
Application
、
Assembly
的 API 检索 XAML 文件,或者从文件系统打开文件。然后使用
XamlReaeder
加载它,这样您就拥有了可以添加到应用程序的合并字典中的最终
ResourceDictionary
实例。以下示例是概念或伪代码:
应用程序.xaml
<ResourcDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DefaultLayoutResources.xaml" />
<ResourceDictionary.MergedDictionaries>
<ResourcDictionary>
默认布局资源.xaml
<ResourcDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DefaultLayoutControlStyles.xaml" />
<ResourceDictionary Source="DefaultLayoutControlTemplates.xaml" />
<ResourceDictionary.MergedDictionaries>
<ResourcDictionary>
PortraitLayoutResources.xaml
<ResourcDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="PortraitLayoutControlStyles.xaml" />
<ResourceDictionary Source="PortraitLayoutControlTemplates.xaml" />
<ResourceDictionary.MergedDictionaries>
<ResourcDictionary>
App.xaml.cs
private ResourceDictionary currentLayoutResources;
protected override async void OnStartup(System.Windows.StartupEventArgs e)
{
// Obtain from database, settings file etc.
var layoutMode = LayOutMode.Portrait;
if (layoutMode is LayoutMode.Portrait)
{
var uri = new Uri("PortraitLayoutResources.xaml");
StreamResourceInfo streamResourceInfo = Application.GetResourceStreameManager(uri);
await using Stream resourceStream = streamResourceInfo.Stream;
var xamlReader = new System.Windows.Markup.XamlReader();
xamlReader.LoadCompleted += OnXamlLoaded;
this.currentLayoutResources = (ResourceDictionary)xamlReader.LoadAsync(resourceStream);
}
}
private void OnXamlLoaded(object? sender, AsyncCompletedEventArgs e)
{
// Remove the default layout
this.Resources.MergedDictionaries.RemoveAt(0);
this.Resources.MergedDictionaries.Add(this.currentLayoutResources);
}