IsWindowPatternAvailable

IsWindowPatternAvailable

我们在MS-WordWebBrowser control中托管WPF application文档。

WebBrowser control在导航到选定的MS-Word文档期间显示以下对话框:

c# - 在浏览器中托管Word-AutomationElement IsWindowPatternAvailable-如何设置它?-LMLPHP

我们尝试使用AutomationElement以编程方式关闭对话框。该代码在测试应用程序中可以正常工作。当我们在实际应用程序中修改代码(edit文件,使用mail merge显示文件)时,只有mail merge部分可以正确关闭对话框。在其他情况下,找不到对话的AutomationElement。

我们发现,当对话框的AutomationElement具有IsWindowPatternAvailable = false时,我们的代码将失败。

有没有办法提前设置此属性?还是为什么在一种情况下为真而在另一种情况下为假的原因?

测试应用程序是“标准WPF应用程序”项目。它仅包含MainWindow.xaml.cs和MainWindow.xaml。
单击按钮将Source设置为WebBrowser

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Thread thread = new Thread(new ThreadStart(backgroundCheck));
        thread.Start();
        this.TestBrowser.Source = new Uri(@"path-to-document.doc");
        thread.Abort();
    }


backgroundCheck搜索特定对话框并调用Open按钮

    private void backgroundCheck()
    {
        Thread.Sleep(500);
        while (true)
        {

            AutomationElement window = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));

            if (window!= null)
            {
                AutomationElement downloadWindow = window.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));

               if (downloadWindow != null)
                {
                    AutomationElement button = downloadWindow.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "4426"));

                    button.SetFocus();
                     (InvokePattern)button.GetCurrentPattern(InvokePattern.Pattern)).Invoke();
                     return;

                }
            }
        }
    }


我们的实际应用程序稍微复杂一些,并使用MVVMPRISM 5WCF。我们使用WCF从服务器加载Word文档。文件保存在%temp%中。

两个ViewModel(编辑文档/显示合并的文档,每个都在different module中)发布eventView订阅:

    public class VmExample
    {
        public delegate void BrowserNavigationEventHandler(string pfad);

        public event BrowserNavigationEventHandler browserNavigate;

        private void navigateToDocument()
        {
             browserNavigate("Path-To-Document.doc");
        }
    }

    public partial class ViewMerge : UserControl
    {

        private VmExample _vm;

        public ViewMerge()
        {
            InitializeComponent();
            this.DataContextChanged += ViewMerge_DataContextChanged;
        }

        private void ViewMerge_DataContextChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            this._vm = e.NewValue as VmExample;

            this._vm.browserNavigate += ViewMerge_browserNavigate;
            this.DataContextChanged -= ViewMerge_DataContextChanged;
        }

        private void ViewMerge_browserNavigate(string path)
        {
            Thread threadCheckDownoadWindow = new Thread(backgroundCheck);
            threadCheckDownoadWindow.Start();
            this.wbBrowser.Source = new Uri(path);
            threadCheckDownoadWindow.Abort();
            this._vm.browserNavigate -= ViewMerge_browserNavigate;
        }

    }


我们已经借助IsWindowPatternAvailable找到了inspect.exe中的区别。当IsWindowPatternAvailable = true时,对话框是Desktop的直接子级,可以找到。当IsWindowPatternAvailable = false时,在TreeViewinspect.exe中看不到对话框,但是我们可以通过单击来访问对话框的属性。
inspect.exe中,我们看到以下ancestors


对话本身
元素类名称:Shell嵌入
网页浏览器
ViewEdit(查看以编辑文档)
应用


当我们使用代码在“合并”模块中编辑文档时,对话框将正确关闭。这两个模块都引用相同的UIAutomation DLL(UIAutomationClient,UIAutomationProvider)。

这里提到了类似的问题:AutomationElement shows up using Inspect.exe but does show not up ...
使用TreeWalker或搜索Subtree的完整AutomationElement.RootElement无效。

欢迎任何IsWindowPatternAvailable如此行为的线索。也欢迎提供有关如何关闭“文件下载”对话框的其他建议。

最佳答案

最终使用UIAutomationEvents在此blog的帮助下找到了解决我的问题的解决方案。

    AutomationEventHandler UIAEventHandler = new AutomationEventHandler(OnUIAEvent);

    Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent,
                    AutomationElement.RootElement,
                    TreeScope.Descendants, UIAEventHandler);
    private static void OnUIAEvent(object src, AutomationEventArgs e)
    {
        AutomationElement element = src as AutomationElement;

        if (element == null)
        {
            return;
        }

        AutomationElement openButton = element.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "4426"));

        if (openButton != null)
        {
            openButton.SetFocus();

            ((InvokePattern)openButton.GetCurrentPattern(InvokePattern.Pattern)).Invoke();
        }
    }

10-05 18:37