WPF中登录窗口的跳转处理
博客分类: 示例
在WPF应用设计中,常常需要在主窗口之前设置一个前置登录窗口,为此整理了一下可行的方案。
示例源码:Jess.Sample.LoginWindow
方案一:添加Program.cs
,模仿Winform初始代码
不做整理,个人不推荐,既然用了WPF,就尽量不把Winform的东西引入进来。
方案二:在主窗体MainWindow的构造函数中处理登录操作
此方案相对局限,若单纯只有个登录操作,可以使用此法 —— 可依据需要调整
InitializeComponent();
的先后顺序。
``` csharp
public partial class MainWindow : Window
{
public MainWindow()
{
WindowLogin win = new WindowLogin();
if (!(win.ShowDialog() ?? false))
{
App.Current.Shutdown();
return;
}
InitializeComponent();
}
}
```
方案三:重写Application
的OnStartup
方法
注意事项:
- 在
OnStartup
中关闭窗体,会导致进入不了主窗体,因此需要手动控制ShutdownMode
【默认值:ShutdownMode.OnLastWindowClose
】- 不得在
App
构造函数中,进行UI显示操作,因为这会导致一些锁的释放,引发OnStartup
提前触发【OnStartup
是在Application
的构造函数中异步调用的】
官方Window.cs
源码的窗体关闭流程中有一段以下代码:
``` csharp
if (((App.Windows.Count == 0) && (App.ShutdownMode == ShutdownMode.OnLastWindowClose))
|| ((App.MainWindow == this) && (App.ShutdownMode == ShutdownMode.OnMainWindowClose)))
{
App.CriticalShutdown(0);
}
```
由此可见,默认情况下,在OnStartup
中调用关闭窗体,会直接导致Shutdown
的调用。
鉴于此,主要有以下修改方式【只要避免内部调用Shutdown
即可】:
保证登录窗体关闭时,不会满足
Shutdown
调用条件
- 全局自己手动控制
Shutdown
:使用ShutdownMode.OnExplicitShutdown
,在需要退出应用时,调用App.Current.Shutdown()
; - 在登录窗体前后,切换
ShutdownMode
:登录前改为ShutdownMode.OnExplicitShutdown
,窗体关闭后,恢复为ShutdownMode.OnLastWindowClose
; - 控制只有主窗体关闭时,才退出程序:指定
MainWindow
,手动启动MainWindow
,不在依赖StartupUri
。
全局手动控制Shutdown
- 设置ShutdownMode为OnExplicitShutdown;
- 在需要退出应用的窗体中,重写OnClosed方法,手动调用
App.Current.Shutdown()
。
``` csharp
public partial class App : Application
{
public App()
{
this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
}
protected override void OnStartup(StartupEventArgs e)
{
WindowLogin win = new WindowLogin();
if (!(win.ShowDialog() ?? false))
{
App.Current.Shutdown();
return;
}
base.OnStartup(e);
}
}
```
``` csharp
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
App.Current.Shutdown();
}
}
```
窗体显示前后切换ShutdownMode
- 直接在登录窗体前后设置
ShutdownMode
即可:
``` csharp
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
WindowLogin win = new WindowLogin();
if (!(win.ShowDialog() ?? false))
{
this.Shutdown();
return;
}
this.ShutdownMode = ShutdownMode.OnLastWindowClose;
base.OnStartup(e);
}
}
```
指定App主窗体MainWindow
- 删除
App.xaml
文件中是StartupUri
属性设置。 - 设置主窗体与程序关闭模式。
``` csharp
public partial class App : Application
{
public App()
{
this.MainWindow = new MainWindow();
this.ShutdownMode = ShutdownMode.OnMainWindowClose;
}
protected override void OnStartup(StartupEventArgs e)
{
WindowLogin win = new WindowLogin();
if (!(win.ShowDialog() ?? false))
{
this.Shutdown();
return;
}
base.OnStartup(e);
this.MainWindow.Show();
}
}
```
补充说明
在上面前两种的OnStartup
的处理中,有个隐藏的问题,他们仍然会去创建MainWindow
。如果想避免初始化MainWindow
,有以下两种方式:
- 在调用
Shutdown
之后调用Environment.Exit(0);
,强制退出。 - 重写
Application
的OnNavigating
方法,设置事件参数的Cancel
属性。
``` csharp
protected override void OnNavigating(NavigatingCancelEventArgs e)
{
e.Cancel = true;
base.OnNavigating(e);
}
```
掘:奇葩史