现在的位置: 首页 > 综合 > 正文

WPF Tips: Window.ShowDialog()方法:Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelp

2013年06月20日 ⁄ 综合 ⁄ 共 3114字 ⁄ 字号 评论关闭

关于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

抱歉!评论已关闭.