Note: Advice in this article will only work for DotNetBrowser 1.
This tutorial explains how to display HTML in WPF applications using DotNetBrowser
and Chrome Developer Tools debugging feature. This can be particularly useful if you want to improve how the appearance of your application's UI looks.
This is what your example app UI will look like, when you compile and run this sample in the Visual Studio:
You can also watch this guide here:
Getting Started
Launch the Visual Studio (Visual Studio 2015 is used in this guide) and create a new WPF application.
Then, add DotNetBrowser
via the the NuGet manager. You can easily find the DotNetBrowser package by searching in the
“Browse” tab.
After you click "Install", the package will be added to your Toolbox.
Add the Licence File
DotNetBrowser is a proprietary component, it only runs in projects containing its licence file.
You can obtain a free 30-days evaluation licence or purchase a commercial licence for your project on the DotNetBrowser homepage.
To add the licence file to the project, right-click on your project's name in the Solution Explorer and choose Add -> Existing Item. In the dialog window specify the directory, where your licence file is stored. Please note, you should set File Type to "All Files" to see the licence file.
After the file is added to the project, select it in the Solution Explorer and set "Build Action"
property to "Embedded Resources"
.
Add two BrowserView components through XAML
Let’s set an initial window size to the whole desktop. To do this, let's include the DotNetBrowser namespace and add its components. Name the components as browserView1
and browserView2
. Divide Grid into two parts with same sizes and put the created DotNetBrowser
components into the created parts. Also, you could add default URL through XAML:
<Window x:Class="CreatingHtmlUI.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:wpf="clr-namespace:DotNetBrowser.WPF;assembly=DotNetBrowser" xmlns:local="clr-namespace:CreatingHtmlUI" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525" WindowState="Maximized"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <wpf:WPFBrowserView Name="browserView1" Grid.Column="0"/> <wpf:WPFBrowserView Name="browserView2" Grid.Column="1"/> </Grid> </Window>
Now let’s include a web page with a style sheet to the current project and set the parameters to those files.
Here is the source code of the web page and the style sheet (please note, that the web page doesn’t contain "OnClick" event on the "Submit" button):
UI.html
<html> <head> <link rel='stylesheet' type='text/css' href='stylesheet.css'> </head> <body> <form action="#"> <label for="login">Login</label> <input type="text" id="login" name="login" value="User" /> <label for="password">Password</label> <input type="password" id="password" name="password" value="123456" /> <input type="submit" value="Submit" /> </form> </body> </html>
stylesheet.css
body { background-color: rgba(50, 60, 60, 0.85); color: white; font: 14px/1.72 'Open Sans', Arial, sans-serif; } form { height: 264px; width: 272px; margin: auto; position: absolute; top: 0; left: 0; bottom: 0; right: 0; } label { display: block; text-transform: capitalize; margin: 14px 0 6px; } input[type="text", type="password"] { height: 36px; width: 100%; padding: 5px 10px; color: #000; font-weight: normal; border: 1px solid #ccc; border-radius: 2px; -webkit-box-shadow: 0 0 0 1px #fff; box-shadow: 0 0 0 1px #fff; outline: none; font: 14px/1.72 'Open Sans', Arial, sans-serif; } input[name="password"] { margin-bottom: 22px; } input[type="text", type="password"]:focus { box-shadow: 0 0 0 1px #ffe5ac; border-color: #ffe5ac; } input[type="submit"] { width: 175px; height: 46px; background: 0 0; color: #fff; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; text-align: center; white-space: nowrap; border: 2px solid #fff; border-radius: 4px; padding: 0 30px 0; vertical-align: middle; cursor: pointer; -webkit-transition: all .15s ease-in; font: 14px/1 'Open Sans', Arial, sans-serif; } input[type="submit"]:focus { background: rgba(255, 255, 255, .1); outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } input[type="submit"]:active { background-image: none; outline: 0; -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); } input[type="submit"]:hover { color: #fff; background: rgba(255, 255, 255, .1); }
Add a FinishLoadingFrameEvent
listener for browserView1
. It will help us track when a page is completely loaded.
Implement the previously designed window
Let’s initialize the primary settings of the MainWindow
. We added the Chromium switch to turn on the Chrome Developer Tools remote debugging feature and set the default URL for both DotNetBrowser
components. In this way we'll be able to control the web page with the style sheet:
С#
public MainWindow() { BrowserPreferences.SetChromiumSwitches("--remote-debugging-port=9222"); InitializeComponent(); browserView1.Browser.LoadURL(System.IO.Path.GetFullPath("UI.html")); browserView2.Browser.LoadURL(browserView1.Browser.GetRemoteDebuggingURL()); }
VB.NET
Public Sub New() BrowserPreferences.SetChromiumSwitches("--remote-debugging-port=9222") InitializeComponent() browserView1.Browser.LoadURL(System.IO.Path.GetFullPath("UI.html")) browserView2.Browser.LoadURL(browserView1.Browser.GetRemoteDebuggingURL()) End Sub
Implement the FinishLoadingFrameEvent handler
Now we will implement the FinishLoadingFrameEvent handler. We should check whether the page is loaded completely before obtaining all HTML elements as a DOM tree. It will help us to find a Submit button and add an event listener to the OnClick event. Let’s name the event handler OnSubmitClicked:
C#
private void browserView1_FinishLoadingFrameEvent(object sender, DotNetBrowser.Events.FinishLoadingEventArgs e) { if (e.IsMainFrame) { DOMDocument document = e.Browser.GetDocument(); List<DOMNode> inputs = document.GetElementsByTagName("input"); foreach (DOMNode node in inputs) { DOMElement element = node as DOMElement; if (element.GetAttribute("type").ToLower().Equals("submit")) { element.AddEventListener(DOMEventType.OnClick, OnSubmitClicked, false); } } } }
VB.NET
Private Sub browserView1_FinishLoadingFrameEvent(ByVal sender As Object, ByVal e As DotNetBrowser.Events.FinishLoadingEventArgs) If e.IsMainFrame Then Dim document As DOMDocument = e.Browser.GetDocument() Dim inputs As List(Of DOMNode) = document.GetElementsByTagName("input") For Each node As DOMNode In inputs Dim element As DOMElement = TryCast(node, DOMElement) If element.GetAttribute("type").ToLower().Equals("submit") Then element.AddEventListener(DOMEventType.OnClick, OnSubmitClicked, False) End If Next End If End Sub
Implement the OnSubmitClicked handler
This handler will read the form data and display a message with obtained values in a separate thread. Such approach allows to avoid deadlocks during call.
DotNetBrowser
has a specific API to access the value property directly, not using cycles. So, we should return the web page as a DOM tree, save the obtained values to the temporary variables, and invoke the MessageBox
:
C#
private void OnSubmitClicked(object sender, DOMEventArgs e) { Task.Run(new Action(() => { string login = string.Empty; string password = string.Empty; DOMDocument document = browserView1.Browser.GetDocument(); login = ((DOMInputElement)document.GetElementById("login")).Value; password = ((DOMInputElement)document.GetElementById("password")).Value; Application.Current.Dispatcher.BeginInvoke(new Action(() => { MessageBox.Show(this, "Login: " + login + "\nPassword: " + password, "Data"); })); })); }
VB.NET
Private Sub OnSubmitClicked(ByVal sender As Object, ByVal e As DOMEventArgs) Task.Run(New Action(Sub() Dim login As String = String.Empty Dim password As String = String.Empty Dim document As DOMDocument = browserView1.Browser.GetDocument() login = (CType(document.GetElementById("login"), DOMInputElement)).Value password = (CType(document.GetElementById("password"), DOMInputElement)).Value Application.Current.Dispatcher.BeginInvoke(New Action(Sub() MessageBox.Show(Me, "Login: " & login & vbLf & "Password: " & password, "Data") End Sub)) End Sub)) End Sub
Compile the project and check the result
To check if the OnClick event works as expected click the Submit button. A message with the current login and password data should appear.
You could also change values in the input fields and Submit button will return up-to-date information. In the same way you could modify the web page using Chrome Developer Tools and watch the changes taking place immediately.
The source code provided in this guide is also available in the attached archive.