【问题标题】:wpf detect open windowwpf检测打开的窗口
【发布时间】:2009-12-05 02:06:23
【问题描述】:

在我的 WPF 应用程序 (csharp) 中,我有一个事件处理程序,当触发时将打开应用程序的新窗口(窗口 B)并显示一些数据。但是,当再次触发事件时,如果新窗口(窗口 B)仍然打开,我不想生成窗口 B 的另一个实例,而只是更新当前实例中显示的数据。所以问题是:如何检测窗口 B 是否已经打开,如果还没有打开,否则只更新数据?

我找到了 Application.Current.Window 集合,但不知何故这对我来说还不起作用。想法?

【问题讨论】:

    标签: wpf events window


    【解决方案1】:

    您可以在 WindowB 中创建一个 LoadWindow() 方法,您可以调用该方法来加载(或刷新)数据,无论窗口是否已打开,该方法都将起作用。当此窗口关闭时是否需要委托来调用:

    private Action ParentCallbackOnClose;
    
    public void LoadWindow( Action parentCallbackOnClose ) {
        // load the data (set the DataContext or whatever)
    
        ParentCallbackOnClose = parentCallbackOnClose;    
    
        // Open the window and activate/bring to the foreground
        Show( );
        Activate( ); 
    }
    

    并让您的窗口关闭事件调用关闭委托:

    private void WindowClosed( object sender, EventArgs e ) {
         ParentCallbackOnClose.Invoke( );
    }
    

    现在,从打开 Window B 的类中,让它保留它打开的那个实例,这样如果 WindowB 在有人尝试重新加载它时已经打开,它只会在现有实例上调用 LoadWindow。比如……

    private WindowB WinB;
    
    private void LoadWindowB(Content content)
    {
        if (WinB == null ){
            WinB = new WindowB( );
        }
        WinB.LoadWindow(content, WindowBClosed);
    }
    

    然后您可以在关闭回调时将其清空 WinB,因此如果 WinB 已关闭,则下次调用 LoadWindowB() 时,它将创建它的新实例:

    private void WindowBClosed( ){
        WinB = null;
    }
    

    【讨论】:

      【解决方案2】:

      由于这是 Google 列出的第一个链接,它是几年前发布的,用于检查 Window 是否已打开的解决方案,我将发布我的答案,以供其他人使用,我觉得这更容易实现。 ChildWindow 仅从 MainWindow 调用,因此其他 Window 不需要进行任何检查。

      private void OpenChildWindow()
      {
          if (this.OwnedWindows.OfType<ChildWindow>().Count() > 0)
          {
              ChildWindow Win = this.OwnedWindows.OfType<ChildWindow>().First();
              Win.Activate();
          }
          else
          {
              ChildWindow Win = new ChildWindow();
              Win.Owner = this;
              Win.Show();
          }
      }
      

      【讨论】:

        【解决方案3】:

        有一种老式的方法可以使用界面来执行此操作。我在 Java 中将此视为一种弥补没有代表的方式(如果我错了,请纠正我)。此方法将允许您检查是否已经打开了一个窗口(任何类型的)。原始响应效果很好,但您也可以通过以下方式进行操作:

        创建界面

        public interface IWindowTracker
        {
            void WindowIsOpened();
            void WindowIsClosed();
        }
        

        在父级上实现接口(从您打开的位置):

        public partial class MainWindow : Window, IWindowTracker
        

        在您的构造函数中,接受一个属于 IwindowTracker 接口的对象。保存实例以备将来使用

            IWindowTracker windowTracker;
            public ProjectManager(IWindowTracker parentWindowTracker)
            {
                windowTracker = parentWindowTracker;
        
                InitializeComponent();
            }
        

        设置对窗口跟踪器对象的调用

            protected override void OnActivated(EventArgs e)
            {
                windowTracker.WindowIsOpened();
                base.OnActivated(e);
            }
        
            protected override void OnClosed(EventArgs e)
            {
                windowTracker.WindowIsClosed();
                base.OnClosed(e);
            }
        

        最后在你的父 WPF 窗口中实现 IWindowTracker

            bool windowIsOpen = false;
        
            public void WindowIsOpened()
            {
                windowIsOpen = true;
            }
        
            public void WindowIsClosed()
            {
                windowIsOpen = false;
            }
        

        这将允许您跟踪窗口是否仍然打开,如果是,则无需打开它的新实例:

                if (!windowIsOpen)
                {
                    remoteProjectManager = new ProjectManager(this);
                    remoteProjectManager.Show();
                }
        
                remoteProjectManager.Focus();
        

        在关闭的窗口上调用 show() 似乎会抛出异常,所以我的猜测是还有其他方法,或者如果您关闭了窗口,则从技术上讲,该窗口已“销毁”

        这样做的好处是我可以检测窗口是否仍然打开并专注于它(以便它再次出现在前面)。

        注意:这有一个缺点,因为在此设置中,它限制您一次只能打开一个窗口(假设您的所有窗口都是这样实现的)。就我而言,我只想在主窗口之外打开一个窗口。

        您可能还想检查您的窗口是否为空,考虑到它可能不是您必须打开的唯一窗口。

        【讨论】:

          【解决方案4】:

          编辑: 哎呀,我的回答是针对 Windows 窗体的。我刚刚看到 WPF 提到。我不确定 WPF 的具体代码是什么,但我想这在概念上并没有那么不同。我认为在 WPF 中,该属性称为 IsVisible 而不是 Visible

          您可以保留窗口的实例(或将其设为Singleton),然后当您需要确定它是否可见时,检查它的 Visible 属性。

          例如:

          if(myWindow.Visible){
            myWindow.Hide();
          }else{
            myWindow.Show();
          }
          

          【讨论】:

            【解决方案5】:

            This article 这是我发现在 WPF 页面之间传递数据的最佳方法。作者使用 KISS 方法提供了一个简单的解决方案。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-03-03
              相关资源
              最近更新 更多