添加遗留 Prism 后为 WPF 加载的两个主要 windows

Two main windows loaded for WPF after adding legacy Prism

我的应用程序使用非常旧的 Prism v4.x 引用并添加了区域管理器和模块,我遇到了问题。结果,它显示了两个 windows,并且它们链接在一起,因此在第一个屏幕中的第二个节目上执行任何操作,或者第一个屏幕未完全加载。

App.xaml.cs 文件:

using System;
using System.Windows;
namespace WpfTestApp
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        [STAThread]
        public static void Main(string[] args)
        {
            try
            {
                var app = new App();
                app.InitializeComponent();
                app.Run();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Fatal Exception occurred!");
            }
        }

        /// <inheritdoc />
        protected override void OnStartup(StartupEventArgs e)
        {
            try
            {
                base.OnStartup(e);
                
                var bootstrapper = new AppBootstrapper();
                bootstrapper.Run();

                base.OnStartup(e);
            }
            catch (Exception ex)
            {
                try
                {
                    MessageBox.Show(ex.ToString(), "App startup");
                }
                finally
                {
                    Current.Shutdown();
                }
            }
        }
    }
}

AppBootstrapper.cs 文件:

using System.Windows;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Prism.UnityExtensions;
using Microsoft.Practices.ServiceLocation;

namespace WpfTestApp
{
    public class AppBootstrapper : UnityBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
            InitializeModules();
            return ServiceLocator.Current.GetInstance<MainWindow>();
        }

        /// <summary>
        /// Runs the initialization steps to ensure that the shell is ready to be displayed. The shell application
        /// object is created and set as the main window of the application.
        /// </summary>
        protected override void InitializeShell()
        {
            base.InitializeShell();

            App.Current.MainWindow = (Window)Shell;
            App.Current.MainWindow.Show();
        }

        protected override void ConfigureModuleCatalog()
        {
            ModuleCatalog.AddModule(new ModuleInfo()
            {
                ModuleName = OutlookModule.NAME,
                ModuleType = typeof(OutlookModule).AssemblyQualifiedName,
                InitializationMode = InitializationMode.WhenAvailable
            });
        }
    }
}

虚拟模块OutlookModule.cs 文件:

using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Unity;

namespace WpfTestApp
{
    [Module(ModuleName = NAME)]
    public class OutlookModule : IModule
    {
        internal const string NAME = "OutlookModule";

        public OutlookModule(IUnityContainer container, IRegionManager regionManager)
        {
        }
        public void Initialize()
        {
        }
    }
}

非标准 WPF 项目文件:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup Label="Globals">
    <SccProjectName>SAK</SccProjectName>
    <SccProvider>SAK</SccProvider>
    <SccAuxPath>SAK</SccAuxPath>
    <SccLocalPath>SAK</SccLocalPath>
  </PropertyGroup>
  <PropertyGroup>
    <TargetFramework>net48</TargetFramework>
    <OutputType>WinExe</OutputType>
    <RootNamespace>SpreadsheetOwnerErrorSampleV3</RootNamespace>
    <AssemblyName>SpreadsheetOwnerErrorSampleV3</AssemblyName>
    <GenerateAssemblyInfo>False</GenerateAssemblyInfo>
    <ExpressionBlendVersion>12.0.51020.0</ExpressionBlendVersion>
    <OutputPath>..\bin\</OutputPath>
    <StartupObject>WpfTestApp.App</StartupObject>
    <EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
    <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
    <Prefer32Bit>true</Prefer32Bit>
    <DebugType>full</DebugType>
    <DebugSymbols>True</DebugSymbols>
  </PropertyGroup>
    <ItemGroup>
        <None Remove="WpfTestApp.csproj.vspscc" />
    </ItemGroup>
  <ItemGroup>
      <Page Include="App.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
    <Compile Include="App.xaml.cs">
      <DependentUpon>App.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
    <Compile Include="AppBootstrapper.cs" />
    <Compile Include="OutlookModule.cs" />
    <Page Include="MainWindow.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
    <Compile Include="MainWindow.xaml.cs">
      <DependentUpon>MainWindow.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
  </ItemGroup>
  <ItemGroup>
    <AppDesigner Include="Properties\" />
  </ItemGroup>

    <ItemGroup>
        <Reference Include="System" />
        <Reference Include="Microsoft.CSharp" />
        <Reference Include="System.Core" />
        <Reference Include="System.Xaml" />
        <Reference Include="UIAutomationProvider" />
        <Reference Include="WindowsBase" />
        <Reference Include="PresentationCore" />
        <Reference Include="PresentationFramework" />
    </ItemGroup>
    <ItemGroup>
        <PackageReference Include="Prism.Desktop.Net40" Version="4.1.1" />
        <PackageReference Include="Prism.UnityExtensions.Net40" Version="4.1.1" />
        <PackageReference Include="System.Windows.Interactivity.WPF" Version="2.0.20525" />
        <PackageReference Include="Unity" Version="2.1.505" />
    </ItemGroup>
  <ItemGroup>
    <BootstrapperPackage Include=".NETFramework,Version=v4.0">
      <Visible>False</Visible>
      <ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
      <Install>true</Install>
    </BootstrapperPackage>
  </ItemGroup>
  <PropertyGroup>
    <LanguageTargets>$(MSBuildExtensionsPath)$(MSBuildToolsVersion)\Bin\Microsoft.CSharp.targets</LanguageTargets>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  </PropertyGroup>
  <Target Name="WorkaroundForXAMLIntellisenseBuildIssue" AfterTargets="_CheckCompileDesignTimePrerequisite">
    <PropertyGroup>
      <BuildingProject>false</BuildingProject>
    </PropertyGroup>
  </Target>
  <Choose>
    <When Condition="'$(MSBuildProjectExtension)' != '.csproj' and '$(MSBuildProjectExtension)' != '.vbproj'">
      <PropertyGroup>
        <LanguageTargets Condition="Exists('$(MSBuildProjectDirectory)$(AssemblyName).csproj')">$(MSBuildToolsPath)\Microsoft.CSharp.targets</LanguageTargets>
        <LanguageTargets Condition="Exists('$(MSBuildProjectDirectory)$(AssemblyName).vbproj')">$(MSBuildToolsPath)\Microsoft.VisualBasic.targets</LanguageTargets>
      </PropertyGroup>
    </When>
  </Choose>
</Project>

请帮助确定为什么加载了两个 Windows 而它应该只是第一个。我知道使用的 Prism 已经过时,我们将来会升级。但是,我需要一个基于此版本的工作示例。所有这些遗留代码都是根据前一段时间的休闲文章实现的:

http://www.infragistics.com/community/blogs/blagunas/archive/2012/09/13/xamdockmanager-a-prism-regionadapter.aspx http://brianlagunas.com/xamdockmanageran-updated-prism-region-adapter/ http://brianlagunas.com/xamdockmanager-prism-region-adapter-update-3/

两者 windows 在 app.Run() 在 CreateShell 或之后执行期间从 App.xaml.cs Main 方法加载。但是,根据文档,这对于应用程序是必需的: https://prismlibrary.com/docs/wpf/legacy/Initializing.html

提前致谢

正如@mm8 所建议的那样,问题似乎出在 App.xaml 本身,它默认在主视图中注入启动行:

<Application x:Class="WpfTestApp.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfTestApp"

             !-> StartupUri="MainWindow.xaml">

    <Application.Resources>
         
    </Application.Resources>
</Application>