【问题标题】:Can I subscribe to an event somewhere in wpf to listen for showDialog or new windows?我可以订阅 wpf 中某处的事件以收听 showDialog 或新窗口吗?
【发布时间】:2016-09-28 21:58:08
【问题描述】:

我想观察有关我的应用程序中所有窗口的某些信息。我有一个窗口(通过 Observables)显示大量信息,但除了轮询之外,我找不到任何可以让我知道所有窗口(以及我的应用程序中所有打开的窗口)的窗口。

我是否可以订阅某个地方,这对于显示任何窗口(@98​​7654323@ 或 .ShowDialog())来说都是一个很好的钩子?

【问题讨论】:

  • 模态对话框阻止了与其窗口的交互事件。在刚才的测试中,我能够创建一个父窗口,它非模态显示一个非子窗口。 public MainWindow() { InitializeComponent(); (new TestWindow()).Show(); }。当MainWindow 显示一个模态子窗口时(MessageBox 会这样做),TestWindow 继续响应用户输入,因为它不是主窗口的子窗口。如果你的第一段是你真正关心的,其余的只是一种假设的方式,那就很容易了。
  • ...也就是说,除非您的意思是希望您的主窗口在有一个模态子窗口时具有响应性。这也很容易:只是不要让孩子模态。如果您希望ShowDialog() 的所有内容都是让孩子保持领先,那么还有其他方法可以做到这一点。
  • 我已经在窗口上调用了 app.xaml.cs 调用 show ,没有设置子级,但是当出现模式对话框时,转储实时窗口不会让我点击它查看诊断信息。我希望所有模态都像在应用程序中那样表现。但是这个忽略任何/所有模态。由于某种原因,作为非孩子打开这个窗口并没有帮助。您的示例案例看起来应该适合我。
  • 如果它不起作用,我猜你可能正在做一些不同的事情。猜不出是什么。
  • @Maslow,当我在 WinForms 中遇到类似问题(开发人员环境中有多个模式对话框)时,我在这里使用了 Marc Gravell 建议的方法:stackoverflow.com/a/428556/1506454 for is-it-possible-to-use-showdialog-without-blocking-all-forms。还没有尝试过 wpf windows :\.如上所述使用window.Show() 不适合我:窗口被另一个模态对话框阻塞

标签: wpf


【解决方案1】:

您必须添加对UIAutomationClient.dllUIAutomationTypes.dll 的引用。

在我的机器上,它们位于C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5

CommonWindow 用作您的公共窗口,它不断更改其所有者。我创建了模态窗口,它可以进一步创建更多的模态窗口,以及最新的一个拥有 CommonWindow,我还将最新的窗口设置为CommonWindowDataContext

using System;
using System.Windows;

using System.Windows.Automation;
using System.Threading;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        CommonWindow _commonWin = new CommonWindow();

        private void Application_Startup(object sender, StartupEventArgs e)
        {            
            Automation.AddAutomationEventHandler(
                   WindowPattern.WindowOpenedEvent,
                   AutomationElement.RootElement,
                   TreeScope.Children,
                   (s, e1) =>
                   {
                       Application.Current.Dispatcher.Invoke(() =>
                       {
                           var windows = Application.Current.Windows;

                           Window w = windows[windows.Count - 1];
                           w.Closing += w_Closing;

                           // First modal window is shown, so count now is 2 (>1)
                           if (App.Current.Windows.Count > 1)
                           {
                               _commonWin.Owner = w;
                               _commonWin.DataContext = w;
                               _commonWin.Show();
                           }
                       });
                   });
        }

        void w_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // Comparison to 3 is important as there would be 3 windows when first modal window is shown
            if (Application.Current.Windows.Count >= 3)
            {
                _commonWin.Owner = Application.Current.Windows[App.Current.Windows.Count - 2];
                _commonWin.DataContext = Application.Current.Windows[App.Current.Windows.Count - 2];
            }
            else
            {
                _commonWin.Close();
            }
        }
    }
}

CommonWindow 只是 WindowCommonWindow.xaml 一样,就像带有代码隐藏的普通 xaml 文件一样。

【讨论】:

  • 好吧,我对在主应用程序中引用自动化/测试框架并不完全满意/满意,但我会试一试这段代码。看起来它可以通过一些调整来工作
  • @Maslow 其他方法是使用钩子。我现在会处理它,并发布那个版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
  • 2011-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多