标签在第二个Window.Show之后没有显示

时间:2013-09-12 15:28:58

标签: c# wpf

我正在修复一个已经存在的应用程序,我遇到了一些奇怪的问题。

在GUI的某些部分,我们的操作需要一些时间。因此,我们创建了一个名为Wait的小窗口,其中包含一条简单的消息Please wait...。我们只需在需要时Show/Hide窗口。

但这是问题所在。我们第二次显示该窗口时,不会显示Please wait... Label in。

Wait.xaml:

<Window x:Class="WpfApplication1.Wait"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Wait" SizeToContent="WidthAndHeight">
    <StackPanel>
        <Label>Please wait...</Label>
    </StackPanel>
</Window>

Wait.xaml.cs

public partial class Wait : Window
{
    public Wait()
    {
        InitializeComponent();
    }
}

最后,我在最小的WPF应用程序中尝试这个:

// The window is shown perfectly
m_WaitWindow.Show();
Thread.Sleep(5000);
m_WaitWindow.Hide();

Thread.Sleep(2000);

// The label is not shown, the window is empty
m_WaitWindow.Show();
Thread.Sleep(5000);
m_WaitWindow.Hide();

我不知道如何解决这个问题,我在UpdateLayout之后尝试了很多像Show但没有效果的事情。

不仅仅是如何解决这个问题的答案,我想明白为什么会这样?

2 个答案:

答案 0 :(得分:1)

正如Hans Passant发布的那样,你应该在除UI线程之外的单独线程上进行长时间的运行。如果你真的坚持在主线程上执行此操作,那么通常会调用Application.DoEvents()之类的东西。这个调用在WPF中不存在,因为它是一种黑客攻击,并且表明你在UI线程上做了太多工作。但是,如果您真的 必须 尝试关闭它,您可以在第二次显示窗口后立即添加此行:

Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { }));

它与Application.DoEvents()基本相同,只有一些小怪癖。然而,更好的解决方案是启动BackgroundWorker来执行长时间运行的过程,同时UI保持活动状态。更多信息here

答案 1 :(得分:0)

正如Hans Passant所说,你正在阻止UI线程。 (不打算像苏斯博士那样回答......)

通过在后台线程中执行等待/繁重操作,可以很容易地解决这个问题。您的最终实现可能会有所不同,具体取决于您使用的.NET和Visual Studio的版本,但您可以通过以下简单示例完成您的工作:

// The window is shown perfectly.
m_WaitWindow.Show();
ThreadPool.QueueUserWorkItem(arg =>
    {
        Thread.Sleep(5000);
        Dispatcher.BeginInvoke(new Action(() => m_WaitWindow.Hide()));

        Thread.Sleep(2000);

        // The window is still shown perfectly, because the UI thread is not being blocked.
        Dispatcher.BeginInvoke(new Action(() => m_WaitWindow.Show()));
        Thread.Sleep(5000);
        Dispatcher.BeginInvoke(new Action(() => m_WaitWindow.Hide()));
    }, null);

注意:在原始情况下,您还应该看到弹出窗口没有响应用户交互 - 这是一个很好的信号,表明您已经阻止了UI线程。