Reputation: 128
We are hosting MS-Word
documents in a WebBrowser control
in a WPF application
.
The WebBrowser control
shows the following dialogue during the navigation to a selected MS-Word document:
We try to close the dialogue programmatically using AutomationElement
. The code works without any problems in a test application. When we adapt the code in our real application (edit
the file, show file with mail merge
), only the mail merge
part is closing the dialogue correctly. In the other case the AutomationElement for the dialogue can not be found.
We have found out that our code is failing when the AutomationElement for the dialogue has IsWindowPatternAvailable = false
.
Is there a way to set this property in advance? Or a reason why it is true in one case and false in another?
The test application is a "standard WPF-Application"-project. It only contains the MainWindow.xaml.cs and MainWindow.xaml.
Clicking a button sets the Source
for the 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
searches for the specific dialogue and invokes the Open
button
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;
}
}
}
}
Our real application is a bit more complex and uses MVVM
, PRISM 5
and WCF
. We use WCF to load the Word documents from a server. The files are saved in %temp%.
The two ViewModel
s (edit document / show merged document, each in a different module
) publish an event
which the View
s subscribe to:
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;
}
}
We have found the difference in IsWindowPatternAvailable
with the help of inspect.exe
. When IsWindowPatternAvailable = true
the dialogue is a direct child of the Desktop
and can be found. When IsWindowPatternAvailable = false
we do not see the dialogue in the TreeView
of inspect.exe
but we can access the properties of the dialogue by clicking on it.
In inspect.exe
we see the following ancestors
:
When we use the code to edit a document in the "merge"-module the dialogue is closed correctly. Both modules reference the same UIAutomation
DLLs (UIAutomationClient, UIAutomationProvider).
A similar problem is mentioned here: AutomationElement shows up using Inspect.exe but does show not up ...
Using a TreeWalker
or searching the complete Subtree
of the AutomationElement.RootElement
do not work.
Any clues why the IsWindowPatternAvailable
behaves that way are welcome. Other suggestions on how to close the File Download dialogue are also welcome.
Upvotes: 2
Views: 317
Reputation: 128
Finally found a solution for my problem with the help of this blog using UIAutomationEvents.
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();
}
}
Upvotes: 0