You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中ShutdownMode与多窗口启动:如何先显示设置窗口再开主窗口?

解决WPF启动前先显示设置窗口的问题

问题根源分析

你原代码触发InvalidOperationException的原因是:WPF默认ShutdownMode为OnLastWindowClose,当用户取消设置窗口时,设置窗口关闭后无其他窗口存在,应用会自动进入关闭流程,此时再修改ShutdownMode就会报错。同时直接在主窗口Loaded事件中打开设置窗口,会导致两个窗口同时显示,不符合需求。


推荐解决方案:在Startup事件中直接处理(最优)

这种方式无需提前创建主窗口,逻辑更清晰且节省资源,步骤如下:

1. 修改App.xaml

移除默认的StartupUri属性,手动指定启动事件处理方法:

<Application x:Class="YourAppName.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Startup="ApplicationStart1">
    <Application.Resources>
    </Application.Resources>
</Application>

2. 编写启动事件处理代码

Public Sub ApplicationStart1(sender As Object, e As StartupEventArgs)
    ' 先设置显式关闭模式,避免设置窗口关闭后应用自动退出
    Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown

    ' 检查设置是否已配置(替换为你的实际检查逻辑)
    Dim settingsConfigured As Boolean = CheckSettingsStatus()

    If Not settingsConfigured Then
        Dim windowSettings As New SettingsView()
        Dim dialogResult = windowSettings.ShowDialog()

        If dialogResult.HasValue AndAlso dialogResult.Value Then
            ' 保存用户配置的设置(替换为你的实际保存逻辑)
            SaveUserSettings(windowSettings)

            ' 创建并启动主窗口
            Dim windowMain As New MainView1()
            Application.Current.MainWindow = windowMain
            Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose
            windowMain.Show()
        Else
            ' 用户取消设置,直接关闭应用
            Application.Current.Shutdown()
        End If
    Else
        ' 已有配置,直接启动主窗口
        Dim windowMain As New MainView1()
        Application.Current.MainWindow = windowMain
        Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose
        windowMain.Show()
    End If
End Sub

' 示例:检查设置是否已配置
Private Function CheckSettingsStatus() As Boolean
    ' 示例逻辑:检查配置文件中是否存在有效数据文件路径
    Dim dataFilePath = My.Settings.DataFilePath
    Return Not String.IsNullOrEmpty(dataFilePath) AndAlso IO.File.Exists(dataFilePath)
End Function

' 示例:保存用户设置
Private Sub SaveUserSettings(settingsWindow As SettingsView)
    ' 示例逻辑:从设置窗口的ViewModel中获取值并保存
    Dim vm = DirectCast(settingsWindow.DataContext, SettingsViewModel)
    My.Settings.DataFilePath = vm.DataFilePath
    My.Settings.Save()
End Sub

备选方案:基于主窗口的处理(适合无法修改App.xaml的场景)

如果必须保留StartupUri指向主窗口,可以在主窗口构造函数中先隐藏自身,再处理设置逻辑:

Public Class MainView1
    Public Sub New()
        InitializeComponent()
        ' 初始化时先隐藏主窗口
        Me.Visibility = Visibility.Hidden

        Dim settingsConfigured As Boolean = CheckSettingsStatus()

        If Not settingsConfigured Then
            Dim windowSettings As New SettingsView()
            Dim dialogResult = windowSettings.ShowDialog()

            If dialogResult.HasValue AndAlso dialogResult.Value Then
                SaveUserSettings(windowSettings)
                ' 设置完成后显示主窗口
                Me.Visibility = Visibility.Visible
            Else
                ' 用户取消,直接关闭应用
                Application.Current.Shutdown()
            End If
        Else
            ' 已有配置,显示主窗口
            Me.Visibility = Visibility.Visible
        End If
    End Sub

    ' 复用上述CheckSettingsStatus和SaveUserSettings方法
End Class

内容的提问来源于stack exchange,提问作者Nostromo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 11:45:05