WebBrowser Element Events and Values





5.00/5 (11 votes)
Sinking WebBrowser button element events and getting/setting input element values programmatically, without a web server.

Introduction
I am in the process of adding a feature to Intertexti in which I can create HTML forms and log the user's data specific to the notecard. Furthermore, I want to be able to do this without requiring a back-end server. The idea is to be able to get/set the values for text input fields and to capture mouse click events for radio buttons, checkboxes, and normal buttons. My search for how to do this took me two a few places:
Attaching delegates to webbrowser HTML elements
Getting text in a webbrowser textbox
A list of HTML DOM event names
The demonstration program utilizes .NET's WebBrowser
control (and if you read
the Intertexti article, yes, I'm ditching webkit.net and, even though I
subsequently got open-webkit-sharp to compile and work, it has so many problems
it wasn't worth persuing.)
The Test Form
I hard-coded the HTML in the test program to render the above web page:
browser.DocumentText="<form>\r\n" + "First name: <input id='firstname' type='text' name='firstname'/><br/>\r\n" + "Last name: <input id='lastname' type='text' name='lastname'/><br/>\r\n" + "Password: <input id='password' type='password' name='pwd'/><br><br/>\r\n" + "<input type='radio' id='male' name='sex' value='male'/>Male<br/>\r\n" + "<input type='radio' id='female' name='sex' value='female'/>Female<br/><br/>\r\n" + "<input type='checkbox' id='bike' name='vehicle' value='Bike'/>I have a bike<br/>\r\n" + "<input type='checkbox' id='car' name='vehicle' value='Car'/>I have a car <br/><br/>\r\n" + "<input type='button' id='ok' value='OK'/><br/>\r\n" + "<input type='button' id='cancel' value='Cancel'/><br/><br/>\r\n" + "</from>";
The DocumentCompleted Event
Event handlers cannot be wired up until the document has loaded, hence we
need to first handle the DocumentCompleted
event:
public class Form1() { public Form1() { ... browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(OnDocumentCompleted); } protected void OnDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { WireUpButtonEvents(); } }
Wiring Up Event Handlers
For the actual element wireups, we use the element method AttachEventHandler
.
Unfortunately, when the event is actually called, the sender parameter is null,
so we instead take advantage of an anonymous method to forward the event to our
real handler, with the element instance provided as the sender. However,
this means we need the actual instance of the element in the anonymous method,
hence the indexed loop rather than a more typical foreach
iterator.
Lastly, the elements of type radio button, checkbox, and button are passed to
the OnElementClicked
handler by wiring up the DOM "onclick
" property, whereas
text elements are passed to the OnElementLostFocus
handler by wiring up the DOM
"onblur
" property.
protected void WireUpButtonEvents() { HtmlElementCollection elements = browser.Document.GetElementsByTagName("input"); // We have to use this form because of the lambda expression that is used to pass // in the element instance to the handler. This is the only way to actually get // the element instance, as the instance is not passed in if we just provide the // event sink method name. for (int i=0; i<elements.Count; i++) { HtmlElement el = elements[i]; string elType = el.GetAttribute("type"); switch (elType) { case "radio": case "checkbox": case "button": { // We need the element instance to know what was clicked. el.AttachEventHandler("onclick", (sender, args) => OnElementClicked(el, EventArgs.Empty)); break; } case "text": { // We need the element instance to know what was clicked. el.AttachEventHandler("onblur", (sender, args) => OnElementLostFocus(el, EventArgs.Empty)); break; } } } }
The Event Handlers
Lastly, the event handlers simply report the event occurrence in the textbox
below the browser control:
protected void OnElementClicked(object sender, EventArgs args) { HtmlElement el = sender as HtmlElement; string elType = el.GetAttribute("type"); string elName = el.GetAttribute("name"); string elValue = el.GetAttribute("value"); tbMessages.Text += "Clicked: " + elType + " " + elName + " " + elValue + "\r\n"; } protected void OnElementLostFocus(object sender, EventArgs args) { HtmlElement el = sender as HtmlElement; string elType = el.GetAttribute("type"); string elName = el.GetAttribute("name"); string elValue = el.GetAttribute("value"); tbMessages.Text += elType + " " + elName + " " + elValue + "\r\n"; }
Restoring State
If you click on the "Set Data" button on the form, the state of the various input elements are set:
protected void SetFormState() { browser.Document.GetElementById("firstname").SetAttribute("value", "Marcia"); browser.Document.GetElementById("lastname").SetAttribute("value", "JohnDoe"); browser.Document.GetElementById("female").SetAttribute("checked", "1"); browser.Document.GetElementById("bike").SetAttribute("checked", ""); browser.Document.GetElementById("car").SetAttribute("checked", "1"); }
Note that to uncheck a checkbox, an empty string is passed as the attribute value. Also note that one does not need to "uncheck" a radio button - the browser handles this state change for all radio buttons grouped by the name attribute.
Conclusion
Hopefully this code has concisely illustrated how to hook into the web browser's events to respond programmatically to button clicks and text value changes, as well as how to restore the web browser's editable controls to a specific state.