【问题标题】:Refer to active Window in WPF?参考 WPF 中的活动窗口?
【发布时间】:2011-01-03 13:51:31
【问题描述】:

如何使用 WinForms 中的 ActiveForm 属性在 C# 中引用 WPF 应用程序的活动窗口?

【问题讨论】:

    标签: c# wpf window


    【解决方案1】:

    一种可能的方法是扫描应用程序中打开的窗口列表并检查其中哪个窗口具有IsActive = true

    Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
    

    不确定是否可能有多个活动窗口,例如,如果有一个模态对话框显示,在这种情况下,对话框的所有者和对话框本身可能是活动的。

    【讨论】:

    • 再次查看我的旧答案,以防万一,最好使用OfType&lt;Window&gt;() 运算符而不是Cast&lt;Window&gt;() 运算符...
    • 太棒了!这使我不必传递对窗口的引用,从而使我的数据结构不受 UI 引用的影响。谢谢!
    • 为了使其更健壮,您也可以使用FirstOrDefault 而不是SingleOrDefault,如果有多个匹配项,则会引发异常。另外,它应该更快一点,因为它接受第一个结果并且不需要检查它是否是唯一的。
    • 有时FirstOrDefaultSingleOrDefault 都返回null,这意味着没有将 IsActive 设置为 true 的窗口。这怎么可能?
    • 如果应用程序本身没有激活?
    【解决方案2】:

    使用 PInvoke 有更好的方法来做到这一点。 Aviads 的答案并非一直有效(有一些带有对话框的极端情况)。

    IntPtr active = GetActiveWindow();
    
    ActiveWindow = Application.Current.Windows.OfType<Window>()
        .SingleOrDefault(window => new WindowInteropHelper(window).Handle == active);
    

    必须首先包含以下导入:

    [DllImport("user32.dll")]
    static extern IntPtr GetActiveWindow();
    

    【讨论】:

    • 呵呵。我自己花了几个小时才发现这一点。我实际上写了和你完全一样的东西&来这里分享它,但你是第一个,所以这是我的投票:P
    • 您能否详细说明边缘情况是什么?
    • @nchaud 我正在使用 AvalonDock,它允许您将工作区拖出主窗口并进入新窗口。但是,这些窗口也标记为IsActive。使用另一种解决方案引发异常(SingleOrDefault 抛出,如果有多个匹配谓词)或者在使用 FirstOrDefault 时没有给我实际的活动窗口
    【解决方案3】:

    我知道这是一个有点老的问题,但我认为我的回答可以帮助某人。

    我的问题是:我有一个 WPF MVVM 应用程序,我需要在第二个视图(即第二个视图模型)中获取我的 MainWindow 实例,以便将标题栏按钮的可见性设置为 visible

    这是我的解决方案:

    MainWindow window = (MyApp.MainWindow)App.Current.MainWindow;
    window.btnSearch.Visibility = System.Windows.Visibility.Visible;
    

    希望这会对某人有所帮助。

    【讨论】:

      【解决方案4】:

      我对这种方式有问题 "Application.Current.Windows.OfType().SingleOrDefault(x => x.IsActive);"特别是因为我正在使用主窗口构建应用程序,然后在选择主窗口时遇到问题。我解决它创建这个:

      在某些基类或 App.xaml.cs 中创建:

             public static Window ActivatedWindow {get;set;}
      

      然后将派生窗口的基类或所有窗口的激活事件放入:

      第一个选项 - 个人窗口基类:

             public class MetroToolWindowBase
             {
               public MetroToolWindowBase()
               {   
                  Activated += new EventHandler(MakeActive); 
               }   
               private void MakeActive(object sender, EventArgs e)
               {
              App.ActivatedWindow= this;
               }
             }
      

      第二个选项-在 Windows 的激活事件中:

         private void XWindow_Activated(object sender,EventArgs e)
          {
           App.ActivatedWindow= this;
          }
      

      【讨论】:

        【解决方案5】:

        另一种方法是使用 user32.dll 中的原生 GetActiveWindow 函数。

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetActiveWindow();
        

        要将其转换为实际的 WPF 窗口:

        IntPtr handle = GetActiveWindow();
        
        HwndSource hwndSource = HwndSource.FromHwnd(handle);
        var window = hwndSource?.RootVisual as Window;
        

        如果在 WinForms 应用程序中托管 WPF 窗口,则应使用 WindowInteropHelper。例如,这使得 Window 所有者可以正常工作:

        var wih = new WindowInteropHelper(window)
        {
            Owner = GetActiveWindow()
        };
        

        我编辑了旧答案,因为我遇到的边缘情况在 Visual Studio 更新后消失了,但可以从答案历史记录中检查。我遇到了一个问题,即在调试时在某些情况下活动窗口为空。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-09
          • 2016-07-23
          • 1970-01-01
          • 1970-01-01
          • 2023-04-02
          • 1970-01-01
          相关资源
          最近更新 更多