【问题标题】:Proper way to ask if a Window is open in WPF询问窗口是否在 WPF 中打开的正确方法
【发布时间】:2013-10-29 13:59:57
【问题描述】:

我的主窗口中有这个点击事件来打开一个新窗口

private void Button_Click(object sender, RoutedEventArgs e)
{
    cm = new CanalesMain();

    cm.Show();

    cm.Canales.setValues();

}

我的 cm 变量在我的主窗口中被定义为一个成员类,因为我需要每 5 分钟加载/刷新一次 setValues() 方法(为此有一个 TimeSpan 和一个 EventHandler)

问题是,在我的“刷新数据”方法中,我有这个 if 语句来询问 cm 变量是否已加载并且不为空(我的意思是,如果窗口曾经打开过或者是否打开过,询问是否t 关闭)

if (cm!=null && cm.IsLoaded)
{
    cm.Canales.setValues();
}

这是询问我的窗口是否打开的正确或最佳方式吗?

【问题讨论】:

  • 有效吗?答案就是你的问题的答案。如果它确实有效,那么您不喜欢实施的什么。 IsLoaded 是查询窗口句柄的事实上的方式。

标签: c# wpf window


【解决方案1】:

严格来说不,这不是正确的方法。 IsLoaded 并不意味着Window 是可见的,只是加载(即使这个可能在大多数情况下是等效的,但这意味着这个窗口已经创建过一次,它有一个句柄,没有提及它的可见性)。

您需要检查的是Visibility 属性(它最终将改变Show()),如果Window 当前可见,它将是Visible,如果没有,它将是Hidden已加载(或已加载但仍处于隐藏状态)。

总结一下:

if (cm != null && cm.Visibility == Visibility.Visible)
{
}

请注意,如果Window 可见,则表明它已被加载(它有一个句柄),但反之亦然(加载的窗口可能不可见,甚至可能在过去不可见) )。

【讨论】:

  • 我会听从你的,因为你先回答了。值得一提的是,Window 的Visibility 在关闭后将保持Visible,而Loaded 将恢复为false。此外,尽管处于LoadedVisible 状态,窗口可能实际上并未被渲染(并且对用户可见)。确保窗口至少被渲染一次的唯一方法是处理其ContentRendered 事件。
  • @MikeStrobel IsLoaded 永远不会恢复为 false,除非对象已被处置。关闭时它会折叠。我同意这并不意味着它是否已被渲染,他没有问所以我什至没有提到它(我通常会使用 RenderSize 属性而不是处理 ContentRendered 事件进行更粗略和简单的检查,但我知道,这并不完全正确)。
  • 我刚刚写的测试用例表明并非如此。属性在Close() 之后立即保留其值;在随后的布局更新后,视觉树已被卸载,IsLoaded 返回falseVisibility 一直保持在 Visible
  • @MikeStrobel 好吧,根据 MSDN,它不应该是,但是......如果你的测试证明......好吧!
【解决方案2】:

还有另一种方法可以检查哪些Windows 当前处于活动状态:

foreach (Window window in Application.Current.Windows)
{ 
    // Check for your Window here
}

如果您的 Window 属于特定类型,那么您可以改为:

foreach (Window window in Application.Current.Windows.OfType<YourWindow>())
{ 
    // Do something with your Window here
}

您的Window 在显示之前不会出现在这里。

【讨论】:

    【解决方案3】:

    我认为扩展方法在这种情况下会非常有用,试试这个:

    public static class WindowsExtensions
    {
       public static bool IsOpened(this Window window)
       {
            return Application.Current.Windows.Cast<Window>().Any(x => x.GetHashCode() == window.GetHashCode());
       }
    }
    

    这使您能够像这样在每个窗口上进行调用:

    var wind = new ChildWindow();
    wind.ShowDialog();
    var isOpened = wind.IsOpened();
    

    你也可以看看这个:How do I know if a WPF window is opened

    更多关于Application.Windows的信息

    【讨论】:

    • 哈希码相等并不一定意味着两个对象实际上相等
    【解决方案4】:

    如果您调用 myWindow.Show() 和 myWindow.Close(),myWindow.IsLoaded 应该会为您提供一个值,您可以使用该值来指示窗口是否打开。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-08
      • 1970-01-01
      相关资源
      最近更新 更多