How to use Javascript on a WPF WebBrowser Control via MVVM How to use Javascript on a WPF WebBrowser Control via MVVM wpf wpf

How to use Javascript on a WPF WebBrowser Control via MVVM


Well if you were working with the site developers to create a solution for your application, then you would use ObjectForScripting to communicate between JavaScript and the app. There a good article here, and another question which might be helpful here.

However as I understand your question, the site is an arbitrary third party site with no affiliation to your application, and you want to auto-fill some form values and submit the form within your code.

To do this you can handle the LoadCompleted event of the WebBrowser. This is called when the loaded document readyState is changed to completed. You can therefore use this event as a hook to then set/read the document form values. Note you will need to add a reference to Microsoft mshtml in the project.

The following is an MVVM style (PRISM) command, which allows an event to bind directly to the ViewModel using behaviors. This is equivalent to registering an event handler in code-behind.

public ICommand LoadCompleted{    get    {        return new EventToCommandWithSender<NavigationEventArgs>(            (s,e) => {                WebBrowser browser = (WebBrowser) sender;               // false if nested frame               if (e.IsNavigationInitiator)               {                   mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)browser.Document;                   // always completed                   var readyState = doc.readyState;                   // populate form                   var name = doc.body.document.getElementById("username");                   name.value = "@TheCodeKing";                   // submit form                   var submit = doc.body.document.getElementById("submit");                   submit.Click();                }        });    }}

Unfortunately the NavigationEventArgs don't provide a way to access the HTML document or request data. It does contain a WebRequest property but this has not been implemented, and will always be null. In my example I've assumed a custom EventToCommandWithSender class which providers the sender as well as the event ARGs when the event fires, but it's down to your own implementation to get access to the sender.


I don't know why this never occurred to me before, but the solution seems so simple.

Instead of having a <WebBrowser> control on the view, use a <ContentControl> and bind its content to a WebBrowser property in your ViewModel. Create the WebBrowser in your ViewModel's constructor, and then you can register the browser's navigation event (or documentloaded) to an event in your ViewModel.

Full browser control from the ViewModel! You can even capture user events, since anything they do to navigate the page will be captured in your ViewModel's navigating event.