关于Window.ShowDialog()方法,有一个常见的容易犯的错误。下面给出这个错误的例子:
DemoA:错误的例子
1. 在WPF项目中,创建一个Windows:DialogWindow
DialogWindow.xaml
<Window x:Class="DemoA.DialogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="I am a dialog window" Height="200" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="140" />
<RowDefinition Height="60" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Margin="12" Content="Hello!" />
<WrapPanel Grid.Row="1" Margin="0" HorizontalAlignment="Center">
<Button Content="OK" Margin="5,0,5,0" Width="60" />
<Button Content="Cancel" Margin="5,0,5,0" Width="60"
Click="ButtonCancelOnClick"/>
</WrapPanel>
</Grid>
</Window>
DialogWindow.xaml.cs
using System.Windows;
namespace DemoA
{
/// <summary>
/// Interaction logic for DialogWindow.xaml
/// </summary>
public partial class DialogWindow : Window
{
public DialogWindow()
{
InitializeComponent();
}
private void ButtonCancelOnClick(object sender, RoutedEventArgs e)
{
this.Close();
}
}
}
然后在MainWindow里面去调用它:
MainWindow.xaml
<Window x:Class="DemoA.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Width="Auto" Height="Auto" Content="Show dialog" Click="ButtonClick" />
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace DemoA
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private DialogWindow dialogWindow = new DialogWindow();
public MainWindow()
{
this.InitializeComponent();
}
private void ButtonClick(object sender, RoutedEventArgs e)
{
dialogWindow.ShowDialog();
}
}
}
这个例子似乎非常寻常。看出它有什么问题了吗?如果您看出问题来了,那么本文对您来说纯属浪费时间,请移步其它文章,谢谢。
好,下面我们运行它。运行时,点击MainWindow窗口的按钮,第一次点击,弹出了DialogWindow对话框,没什么问题。点击“Cancel”按钮关闭DialogWindow对话框,再次点击MainWindow窗口的按钮,这时候问题出现了,抛出了以下异常:
An unhandled exception of type 'System.InvalidOperationException' occurred in PresentationFramework.dll
Additional information: Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed.
如何解决这个问题呢?解决方案如下:DemoB
DialogWindow.xaml.cs
using System.Windows;
namespace DemoB
{
/// <summary>
/// Interaction logic for DialogWindow.xaml
/// </summary>
public partial class DialogWindow : Window
{
private static DialogWindow staticInstance = null;
public DialogWindow()
{
this.InitializeComponent();
this.Closed += WindowOnClosed;
}
public static DialogWindow GetInstance()
{
if (staticInstance == null)
{
staticInstance = new DialogWindow();
}
return staticInstance;
}
private void ButtonCancelOnClick(object sender, RoutedEventArgs e)
{
this.Close();
}
private void WindowOnClosed(object sender, System.EventArgs e)
{
staticInstance = null;
}
}
}
MainWindow.xaml.cs
using System.Windows;
namespace DemoB
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
private void ButtonClick(object sender, RoutedEventArgs e)
{
DialogWindow.GetInstance().ShowDialog();
}
}
}
这样,每次调用Window.ShowDialog()方法的时候,都创建了一个新的DialogWindow实例,所以问题得以解决。
参考:
同样的疑问,在StackOverflow上的讨论如下:
《WPF: Cannot reuse window after it has been closed》
http://stackoverflow.com/questions/3568233/wpf-cannot-reuse-window-after-it-has-been-closed