WPF窗口显示Show和ShowDialog的区别

前言

在WPF中,ShowDialog()Show() 是两种不同的方法用于显示窗口,它们有以下区别:

ShowDialog() 方法

  • ShowDialog() 方法用于显示一个模态窗口,也就是说,它会阻塞调用代码,直到显示的窗口关闭为止。
  • 调用 ShowDialog() 方法后,程序的执行会暂停在此处,直到用户关闭了模态对话框并返回一个指定的结果(例如 DialogResult)。
  • 使用 ShowDialog() 方法时,可以通过设置窗口的 DialogResult 属性来指定窗口关闭时返回的结果。
1
2
3
4
5
var result = dialog.ShowDialog();
if (result.HasValue && result.Value)
{
// 处理窗口操作成功的情况
}

Show() 方法

Show() 方法用于显示一个非模态窗口,也就是说,调用 Show() 后,窗口会以非阻塞的方式显示,允许用户同时与应用程序中的其他窗口或控件交互。

调用 Show() 方法后,程序会继续执行后续代码,不会等待窗口的关闭。

1
2
dialog.Show();
// 这里可以立即执行后续代码

窗口所有权(Owner)的设置

  • 在使用 ShowDialog() 方法显示窗口时,通常会设置一个父窗口作为该窗口的 Owner。这样可以确保模态窗口与其 Owner 之间有逻辑上的层次关系。
  • 使用 Show() 方法显示窗口时,也可以手动设置 Owner,但这不是必须的,窗口可以独立显示而没有 Owner。

返回值

  • ShowDialog() 方法返回一个 bool? 类型的值,表示窗口的 DialogResult

    这个值通常用于确定用户关闭窗口时的操作结果。

  • Show() 方法没有返回值,因为它不会阻塞调用代码,而是立即返回并允许用户与应用程序的其他部分进行交互。

总结来说,选择使用 ShowDialog() 还是 Show() 取决于你的需求:

如果需要一个模态对话框,阻塞用户与应用程序其他部分的交互直到窗口关闭,就使用 ShowDialog()

如果希望窗口以非模态方式显示,并允许用户在显示窗口的同时继续操作应用程序的其他部分,就使用 Show()

ShowDialog窗口关闭

在WPF中,使用 ShowDialog() 方法显示的窗口可以通过以下几种方式关闭:

关闭窗口并返回结果

当调用 ShowDialog() 方法显示窗口后,可以通过设置窗口的 DialogResult 属性来指定窗口的返回结果。

例如,可以设置为 true 表示窗口操作成功,或者其他自定义值。

使用 Close() 方法来关闭窗口,此时 ShowDialog() 方法会返回对应的 DialogResult 值。

1
2
3
// 在对话框窗口中设置 DialogResult,并关闭窗口
this.DialogResult = true;
this.Close();

取消或关闭窗口

如果窗口的操作取消或者不需要返回特定结果,可以直接调用窗口的 Close() 方法来关闭窗口。

1
2
// 直接关闭窗口
this.Close();

处理窗口关闭事件

在对话框窗口中,可以通过处理 Closing 事件来执行特定的操作(例如验证或取消关闭操作)。

1
2
3
4
5
6
// 处理窗口关闭事件
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// 执行验证或其他操作
// e.Cancel = true; 可以取消窗口关闭
}

总结来说,使用 ShowDialog() 方法显示的窗口在关闭时通常会设置 DialogResult 属性来返回结果,然后调用 Close() 方法关闭窗口。

另外,可以通过处理 Closing 事件来添加额外的关闭逻辑。

ShowDialog后代码不执行

在WPF中,当你使用 ShowDialog() 方法显示一个窗口时,显示的窗口会阻塞调用代码的执行,直到该窗口被关闭为止。

这是因为 ShowDialog() 方法创建了一个模态对话框,它会把焦点和交互限制在当前窗口上,直到用户关闭该窗口为止。

如果想让窗口打开后延迟关闭可以这样做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void ShowAsDialogDelayClose(string message, double sec)
{
MessageWindow messageWindow = new MessageWindow(
1,
"消息提示",
message
) { Topmost = true };
Console.WriteLine($@"延迟{sec}秒关闭");
Task.Run(
() =>
{
Thread.Sleep((int)(sec * 1000));
messageWindow.Dispatcher.Invoke(
() =>
{
messageWindow.Close();
}
);
}
);
messageWindow.ShowDialog();
}

自定义消息提示框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<Window
x:Class="SchoolClient.Wins.MessageWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:Z.Views;assembly=Z"
Name="弹窗提示"
Title="MessageWindow"
Width="400"
Height="200"
Background="#f5f7f9"
MouseMove="Window_MouseMove"
ResizeMode="NoResize"
ShowInTaskbar="False"
Style="{StaticResource ZWinStyle}"
Topmost="True"
WindowStartupLocation="CenterScreen"
WindowState="Normal"
mc:Ignorable="d">
<views:ZClippingBorder
Background="White"
BorderBrush="#f5f7f9"
BorderThickness="1"
CornerRadius="0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="{StaticResource BarTopHeight}" />
<RowDefinition Height="*" />
<RowDefinition Height="1" />
<RowDefinition Height="{StaticResource BarBottomHeight}" />
</Grid.RowDefinitions>

<Grid
Grid.Row="0"
Background="#f5f7f9"
Visibility="Visible">
<Label
x:Name="LblTitle"
Margin="16,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Content=""
FontSize="18"
Foreground="#333333" />
</Grid>
<Grid Grid.Row="1" Background="White">
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<TextBlock
x:Name="TbkContent"
Margin="8,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="18"
Foreground="#343434"
Text=""
TextWrapping="Wrap" />
</StackPanel>
</Grid>

<Rectangle
Grid.Row="2"
Height="1"
Fill="#EEEEEE" />
<StackPanel
Grid.Row="3"
Margin="0,0,0,0"
HorizontalAlignment="Center"
Orientation="Horizontal">
<views:ZRoundButton
x:Name="BorCancel"
Width="138"
Height="36"
Margin="0,0,40,0"
Background="White"
BorderBrush="#339DFF"
BorderRadius="8"
BorderThickness="1"
Click="BtnCancel_Click"
Content="取消"
Cursor="Hand"
FontSize="16"
Foreground="#409EFE" />
<views:ZRoundButton
Width="138"
Height="36"
Background="#409EFE"
BorderBrush="#339DFF"
BorderRadius="8"
BorderThickness="1"
Click="BtnOK_Click"
Content="确定"
Cursor="Hand"
FontSize="16"
Foreground="White" />
</StackPanel>
</Grid>
</views:ZClippingBorder>
</Window>

窗口样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="ZWinStyle" TargetType="Window">
<Setter Property="AllowsTransparency" Value="False" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome
CaptionHeight="0"
CornerRadius="0"
GlassFrameThickness="-1"
NonClientFrameEdges="None"
ResizeBorderThickness="0"
UseAeroCaptionButtons="False" />
</Setter.Value>
</Setter>

<Style.Triggers>
<Trigger Property="WindowState" Value="Maximized">
<Setter Property="BorderThickness" Value="6" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>

C#代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System;
using System.Threading;

/// <summary>
/// MessageWindow.xaml 的交互逻辑
/// </summary>
public partial class MessageWindow
{
/// <summary>
/// 提示框
/// </summary>
/// <param name="messageType">取消按钮 1不显示2显示</param>
/// <param name="title">标题</param>
/// <param name="content">消息内容</param>
private MessageWindow
(
int messageType,
string title,
string content
)
{
InitializeComponent();
BorCancel.Visibility = messageType == 2 ? Visibility.Visible : Visibility.Collapsed;
LblTitle.Content = title;
if (!string.IsNullOrWhiteSpace(content))
{
if (content.Length > 143)
{
content = content.Substring(0, 140) + "...";
}
TbkContent.Text = content;
}
else
{
TbkContent.Text = "";
}
}

/// <summary>
/// 取消
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnCancel_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
Close();
}

/// <summary>
/// 确定
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnOK_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
Close();
}

private void Window_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
DragMove();
}
}

/// <summary>
/// 消息提示框
/// </summary>
/// <param name="messageStr">消息</param>
/// <param name="title"></param>
/// <returns></returns>
public static void ShowAsDialog(string messageStr, string title)
{
MessageWindow messageWindow = new MessageWindow(
1,
title,
messageStr
) { Topmost = true };
messageWindow.ShowDialog();
}

/// <summary>
/// 消息提示框
/// </summary>
/// <param name="message">消息</param>
/// <returns></returns>
public static void ShowAsDialog(string message)
{
const string title = "提示";
ShowAsDialog(message, title);
}

/// <summary>
/// 显示消息并消失
/// </summary>
/// <param name="message"></param>
/// <param name="sec"></param>
/// <returns></returns>
public static void ShowAsDialogDelayClose(string message, double sec)
{
MessageWindow messageWindow = new MessageWindow(
1,
"消息提示",
message
) { Topmost = true };
Console.WriteLine($@"延迟{sec}秒关闭");
Task.Run(
() =>
{
Thread.Sleep((int)(sec * 1000));
messageWindow.Dispatcher.Invoke(
() =>
{
messageWindow.Close();
}
);
}
);
messageWindow.ShowDialog();
}

/// <summary>
/// 消息提示框
/// </summary>
/// <param name="title">标题</param>
/// <param name="messageStr">消息</param>
/// <returns></returns>
public static MessageBoxResult ShowWithResult(string messageStr, string title)
{
if (string.IsNullOrWhiteSpace(title))
{
title = "提示";
}
MessageWindow messageWindow = new MessageWindow(
2,
title,
messageStr
);
bool? result = messageWindow.ShowDialog();
if (result.HasValue && result.Value)
{
return MessageBoxResult.OK;
}
return MessageBoxResult.Cancel;
}
}

调用

消息显示手动关闭

1
MessageWindow.ShowAsDialog("上传成功");

消息显示后关闭

1
MessageWindow.ShowAsDialogDelayClose("发送资源成功", 1.5);

根据结果处理

1
2
3
4
if (MessageWindow.ShowWithResult("确定要关闭页面?", "提示") == MessageBoxResult.OK)
{

}