MainActivity.java
public String URI = null;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0 && resultCode == RESULT_OK)
{
Uri pickedImage = data.getData();
URI = pickedImage.toString();
}
}
public String GetURI()
{
return URI;
}
WebAppInterface.java
#JavascriptInterface
public void GetPicture()
{
Intent galleryIntent = new Intent(Intent.ACTION_PICK);
galleryIntent.setType("image/*");
((MainActivity) mContext).startActivityForResult(galleryIntent, 0);
}
#JavascriptInterface
public String GetURI()
{
return getRealPathFromURI(mContext, Uri.parse(((MainActivity) mContext).GetURI()));
}
I'm using the following Javascript functions
function GetPicture()
{
Android.GetPicture();
}
function loadImage()
{
document.getElementById("img").src = Android.GetURI();
}
The first one is used to get the picture and store the full path in a string. The second function is used to obtain the the full path from the string.
Currently this is working because I'm first calling GetPicture and then loadImage.
But I want to "merge" the functions.
So the Javascript would be:
function loadImage()
{
document.getElementById("img").src = Android.GetPicture();
}
So I changed the code from WebAppInterface.java to this:
#JavascriptInterface
public String GetPicture()
{
Intent galleryIntent = new Intent(Intent.ACTION_PICK);
galleryIntent.setType("image/*");
((MainActivity) mContext).startActivityForResult(galleryIntent, 0);
return ((MainActivity) mContext).GetURI();
}
But it's not working. I think I know why because GetURI is being called before the string URI has been set.
So how do I fix this problem?
If somebody knows a better title please let me know.
OK I think I found a solution but I don't know if this is the best way to do it.
So for those who want to know how I fixed it:
I changed the GetPicture method
#JavascriptInterface
public String GetPicture()
{
Intent galleryIntent = new Intent(Intent.ACTION_PICK);
galleryIntent.setType("image/*");
((MainActivity) mContext).startActivityForResult(galleryIntent, 0);
while(((MainActivity) mContext).IsFinished == false){}
return ((MainActivity) mContext).GetURI();
}
In MainActivity.java I added a public boolean called IsFinished (set to false) and it is going to be true when the user picked an image (onActivityResult).
So the code will be:
public String URI = null;
public boolean IsFinished = false;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0 && resultCode == RESULT_OK)
{
Uri pickedImage = data.getData();
URI = pickedImage.toString();
IsFinished = true;
}
}
public String GetURI()
{
return URI;
}
Related
public static String dataFromJs;
public void androidMethod() {
// initialize static String dataFromJs.
dataFromJs = "";
webView.evaluateJavascript("javascript:jsFuction();", new ValueCallback<String>() {
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onReceiveValue(String s) {
JsonReader reader = new JsonReader(new StringReader(s));
reader.setLenient(true);
try {
if (reader.peek() != JsonToken.NULL) {
if (reader.peek() == JsonToken.STRING) {
// get string value from javascript and I want to use the value
dataFromJs = reader.nextString();
}
}
} catch (IOException e) {
Log.e("TAG", "MainActivity: IOException", e);
} finally {
try {
reader.close();
} catch (IOException e) {
// NOOP
}
}
}
});
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if(url.endsWith("menu/page.do")) {
androidMethod();
// do something with dataFromJs..
}
}
The androidMethod is my method in android.
I try to use the str what I receieved from javascript.
but webView.evaluateJavascript method always return null at the first time,
the webView.evaluateJavascript is called again and return string value correctly.
Since the return value is null at the first time, so I can't use the androidMethod in another method.
Anyone has good solution??
is it have something to do with this log (The application may be doing too much work on its main thread.) ?
Thank you!
I have a problem with running a c# method from js that is inside of a webview in xamarin.
I have a c# method like this:
public void simpleMethod(int a,string b,bool c){
string[] data;
if(c){
data[a] = b;
}
}
Now how do I call this method from the javasript?
You can create a Custom Renderer of WebView
Create a custom WebView in Forms
public class HybridWebView : View
{
Action<int, string, bool> action;
public static readonly BindableProperty UriProperty = BindableProperty.Create (
propertyName: "Uri",
returnType: typeof(string),
declaringType: typeof(HybridWebView),
defaultValue: default(string));
public string Uri {
get { return (string)GetValue (UriProperty); }
set { SetValue (UriProperty, value); }
}
public void RegisterAction (Action<int, string, bool> callback)
{
action = callback;
}
public void Cleanup ()
{
action = null;
}
public void InvokeAction (int a,string b,bool c)
{
if (action == null ) {
return;
}
action.Invoke (a,b,c);
}
}
in ContentPage
The HybridWebView instance will be used to display a native web control on each platform. It's Uri property is set to an HTML address , and which will be displayed by the native web control.
The HybridWebViewPage registers the action to be invoked from JavaScript, as shown in the following code example:
public partial class xxxPage : ContentPage
{
public xxxPage ()
{
//...
hybridWebView.RegisterAction ((a,b,c) => simpleMethod(a,b,c));
}
public void simpleMethod(int a,string b,bool c)
{
string[] data;
if(c){
data[a] = b;
}
}
}
<ContentPage.Content>
<local:HybridWebView x:Name="hybridWebView" Uri="https://learn.microsoft.com"
HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</ContentPage.Content>
in your html file
For example you want to call the method when click a button
<button type="button" onclick="javascript:invokeCSCode(a,b,c);">Invoke C# Code</button>
//...
<script type="text/javascript">
function invokeCSCode(a,b,c) {
try {
invokeCSharpAction(a,b,c);
}
catch (err){
log(err);
}
}
Creating the Custom Renderer on iOS
[assembly: ExportRenderer (typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace CustomRenderer.iOS
{
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>, IWKScriptMessageHandler
{
const string JavaScriptFunction = "function invokeCSharpAction(a,b,c){window.webkit.messageHandlers.invokeAction.postMessage(a,b,c);}";
WKUserContentController userController;
protected override void OnElementChanged (ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged (e);
if (e.OldElement != null) {
userController.RemoveAllUserScripts ();
userController.RemoveScriptMessageHandler ("invokeAction");
var hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup ();
}
if (e.NewElement != null) {
if (Control == null) {
userController = new WKUserContentController ();
var script = new WKUserScript (new NSString (JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
userController.AddUserScript (script);
userController.AddScriptMessageHandler (this, "invokeAction");
var config = new WKWebViewConfiguration { UserContentController = userController };
var webView = new WKWebView (Frame, config);
SetNativeControl (webView);
}
Control.LoadRequest (new NSUrlRequest (new NSUrl (Element.Uri, false)));
}
}
public void DidReceiveScriptMessage (WKUserContentController userContentController, WKScriptMessage message)
{
Element.InvokeAction (message.Body.ToString ());
}
}
}
In addition, Info.plist must be updated to include the following values:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Creating the Custom Renderer on Android
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace CustomRenderer.Droid
{
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, Android.Webkit.WebView>
{
const string JavascriptFunction = "function invokeCSharpAction(a,b,c){jsBridge.invokeAction(a,b,c);}";
Context _context;
public HybridWebViewRenderer(Context context) : base(context)
{
_context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
Control.RemoveJavascriptInterface("jsBridge");
var hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup();
}
if (e.NewElement != null)
{
if (Control == null)
{
var webView = new Android.Webkit.WebView(_context);
webView.Settings.JavaScriptEnabled = true;
webView.SetWebViewClient(new JavascriptWebViewClient($"javascript: {JavascriptFunction}"));
SetNativeControl(webView);
}
Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
Control.LoadUrl(Element.Uri);
}
}
}
}
public class JavascriptWebViewClient : WebViewClient
{
string _javascript;
public JavascriptWebViewClient(string javascript)
{
_javascript = javascript;
}
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
view.EvaluateJavascript(_javascript, null);
}
}
public class JSBridge : Java.Lang.Object
{
readonly WeakReference<HybridWebViewRenderer> hybridWebViewRenderer;
public JSBridge (HybridWebViewRenderer hybridRenderer)
{
hybridWebViewRenderer = new WeakReference <HybridWebViewRenderer> (hybridRenderer);
}
[JavascriptInterface]
[Export ("invokeAction")]
public void InvokeAction (int a,string b,bool c)
{
HybridWebViewRenderer hybridRenderer;
if (hybridWebViewRenderer != null && hybridWebViewRenderer.TryGetTarget (out hybridRenderer))
{
hybridRenderer.Element.InvokeAction (a,b,c);
}
}
}
You don't.
Basically you have to detect / trigger a piece of javascript code, detect it with your C# webview configuration/initialization code, and then execute your C#.
Take a look at https://developer.android.com/reference/android/webkit/JavascriptInterface for android to understand what I'm saying, and implement it on Android.
For iOS you have a WKWebview listener that you can use to receive informations from your webpage.
I have a WebView which I use to load some html content locally in my app. It first loads the content, then calls a JavaScript function which then scrolls the WebView to a particular position.
The following code illustrates how I do this:
public class MyActivity extends Activity {
private WebView web1;
private int ID;
private MyWebViewClient webViewClient1;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
// Get the ID of the law to be loaded.
ID = getIntent().getIntExtra("element_id", 1);
web1 = (WebView) findViewById(R.id.web1);
web1.getSettings().setJavaScriptEnabled(true);
// Initialize the webViewClients.
webViewClient1 = new MyWebViewClient(true);
web1.setWebViewClient(webViewClient1);
displayArticle(web1);
}
private void displayArticle (WebView wv) {
StringBuilder sb = new StringBuilder();
// Code to build the HTML String.
String finalHtml = sb.toString();
wv.loadDataWithBaseURL("file:///android_asset/html/", finalHtml, "text/html", "UTF-8", null);
}
private class MyWebViewClient extends WebViewClient {
String urlToLoad;
MyWebViewClient (boolean setUrlToLoad) {
if (setUrlToLoad) {
setUrlToLoad();
}
}
public void setUrlToLoad () {
this.urlToLoad = "javascript:(function () {" +
"var elem = document.getElementById('e"+ID+"');" +
"var x = 0;" +
"var y = 0;" +
"while (elem != null) {" +
"x += elem.offsetLeft;" +
"y += elem.offsetTop;" +
"elem = elem.offsetParent;" +
"}" +
"window.scrollTo(x, y);" +
"})()";
}
#Override
public void onPageStarted (WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
Log.d("Pages", "Page loading started");
}
#Override
public void onReceivedError (WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
Log.d("Pages", "Webview content load error");
}
#Override
public void onPageFinished (WebView view, String url) {
super.onPageFinished(view, url);
Log.d("Pages", "Page loading finished");
if (urlToLoad != null) {
// Scroll to the position.
view.loadUrl(urlToLoad);
urlToLoad = null;
}
}
}
}
In the above code, the callback functions in the MyWebViewClient class are called for the first request using wv.loadDataWithBaseURL in the displayArticle(WebView wv) function, but when the request is finished and onPageFinished is called, the view.loadUrl(urlToLoad); call does not invoke another set of callbacks from MyWebViewClient. I am not quite sure why since it must be the same WebView I originally used and it should have the same instance of MyWebViewClient set.
Moreover, there are other loadUrl calls that I make with the same WebView, and this behaviour persists.
I would really appreciate if someone could explain why this happens.
loadUrl("javascript:...") is a bit of a special case: it evaluates the JavaScript code in the current page's context (just like <a href='javascript:...'>clicky</a> would) and therefore you won't get onPageStarted/onPageFinished callbacks.
I am trying to make a phonegap/cordova plugin which is for converting speech to text using RecognizerIntent. The following is my code of the plugin class:
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
this.callbackContext = callbackContext;
try {
if (ACTION_INVOKE_SPEECH_RECOG.equals(action)) {
//JSONObject arg_object = args.getJSONObject(0);
Intent calIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
calIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US");
this.cordova.setActivityResultCallback(SpeechToTextPlugin.this);
this.cordova.getActivity().startActivityForResult(calIntent,REQUEST_CODE );
callbackContext.success("Completed Main Activity");
}
callbackContext.error("Invalid action");
return false;
} catch(Exception e) {
System.err.println("Exception: " + e.getMessage());
callbackContext.error(e.getMessage());
return false;
}
}
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode == Activity.RESULT_OK) {
JSONObject obj = new JSONObject();
try {
//obj.put("TEXT", intent.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS).toString());
callbackContext.success(intent.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS).toString());
}catch(JSONException e){
}
super.onActivityResult(requestCode, resultCode, intent);
}
}
I pass the recognized text to the javascript invoking the execute method. Right now, after making a call to startActivityForResult, the execute function returns back. How do I pass the recognized word to the js?
You have to use
sendJavascript("yourJSClass.yourJSMethod();");
or just
sendJavascript("yourJSMethod();");
Of course you will have to have:
yourJSMethod = function() {}
in your JS
I am working on a web scraper in C# where I have a web browser control that loads a web page, I then collect data and depending on the data also acting on it. My problem is that I need to write some data to a input (textbox) that has listeners. The input control never shows a value in the html, it is handled by some Javascript that is fired from events on the control. I can set a value to the controls value parameter but it is as it is missing when I click OK on the form.
I have searched the web for days and I now know how to call Javascript from C# but it's the Javascript function on the input i cannot understand.
The input control looks like this:
<div id="size_1" class="incrementControl" style="width: 68px;">
<input id="size_1-input" class="hasListeners" maxlength="6" tabindex="103" value="" style="width:52px">
<a id="size_1-up" class="up hasListeners" style="left:52px" href="javascript:void(0)"> </a>
<a id="size_1-down" class="down hasListeners" style="left:52px" href="javascript:void(0)"> </a>
</div>
The input controls event keyup, keydown, change, keypress and blur all call this Javascript:
function (a)
{
return typeof f != "undefined" && (!a || f.event.triggered !== a.type) ? f.event.dispatch.apply(i.elem, arguments) : b;
}
I have tried invoking different events like onClick and clicking the control programmatically but nothing works?! I donĀ“t know how to call this Javascript function since it doesn't have a name and what to pass as a parameter?
Most grateful for any help or ideas!
You can use Watin. It support Webbrowser control and Internet Explorer.
Here are a number of extension methods (built on top of WatiN) that allow you to (amongst other things) to wait for JS objects or events:
using System;
using System.Threading;
using FluentSharp.Web35;
using FluentSharp.WinForms;
using FluentSharp.CoreLib;
using FluentSharp.CoreLib.API;
namespace FluentSharp.Watin
{
public static class WatiN_IE_ExtensionMethods_Javascript
{
public static object invokeScript(this WatiN_IE ie, string functionName)
{
return ie.invokeScript(functionName, null);
}
public static object invokeScript(this WatiN_IE ie, string functionName, params object[] parameters)
{
//"[WatiN_IE] invokeScript '{0}' with parameters:{1}".info(functionName ,parameters.size());
return ie.invokeScript(true, functionName, parameters);
}
public static object invokeScript(this WatiN_IE ie, bool waitForExecutionComplete, string functionName, params object[] parameters)
{
var sync = new AutoResetEvent(false);
object responseValue = null;
ie.WebBrowser.invokeOnThread(
()=>{
var document = ie.WebBrowser.Document;
if (parameters.isNull())
responseValue = document.InvokeScript(functionName);
else
responseValue = document.InvokeScript(functionName, parameters);
sync.Set();
});
if (waitForExecutionComplete)
sync.WaitOne();
return responseValue;
}
public static object invokeEval(this WatiN_IE ie, string evalScript)
{
var evalParam = "(function() { " + evalScript + "})();";
//"[WatiN_IE] invokeEval evalParam: {0}".debug(evalParam);
return ie.invokeScript("eval", evalParam);
}
public static WatiN_IE.ToCSharp injectJavascriptFunctions(this WatiN_IE ie)
{
return ie.injectJavascriptFunctions(false);
}
public static WatiN_IE.ToCSharp injectJavascriptFunctions(this WatiN_IE ie, bool resetHooks)
{
if (ie.WebBrowser.isNull())
"in InjectJavascriptFunctions, ie.WebBrowser was null".error();
else
{
if (ie.WebBrowser.ObjectForScripting.isNull() || resetHooks)
{
ie.WebBrowser.ObjectForScripting = new WatiN_IE.ToCSharp();
"Injecting Javascript Hooks * Functions for page: {0}".debug(ie.url());
ie.eval("var o2Log = function(message) { window.external.write(message) };");
ie.invokeScript("o2Log","Test from Javascript (via toCSharp(message) )");
ie.eval("$o2 = window.external");
"Injection complete (use o2Log(...) or $o2.write(...) to talk back to O2".info();
return (ie.WebBrowser.ObjectForScripting as WatiN_IE.ToCSharp);
}
else
{
if((ie.WebBrowser.ObjectForScripting is WatiN_IE.ToCSharp))
return (ie.WebBrowser.ObjectForScripting as WatiN_IE.ToCSharp);
else
"in WatiN_IE injectJavascriptFunctions, unexpected type in ie.WebBrowser.ObjectForScripting: {0}".error(ie.WebBrowser.ObjectForScripting.typeName());
}
}
return null;
}
public static object downloadAndExecJavascriptFile(this WatiN_IE ie, string url)
{
"[WatiN_IE] downloadAndExecJavascriptFile: {0}".info(url);
var javascriptCode = url.uri().getHtml();
if (javascriptCode.valid())
ie.eval(javascriptCode);
return ie;
}
public static WatiN_IE injectJavascriptFunctions_onNavigate(this WatiN_IE ie)
{
ie.onNavigate((url)=> ie.injectJavascriptFunctions());
return ie;
}
public static WatiN_IE setOnAjaxLog(this WatiN_IE ie, Action<string, string,string,string> onAjaxLog)
{
(ie.WebBrowser.ObjectForScripting as WatiN_IE.ToCSharp).OnAjaxLog = onAjaxLog;
return ie;
}
public static WatiN_IE eval_ASync(this WatiN_IE ie, string script)
{
O2Thread.mtaThread(()=> ie.eval(script));
return ie;
}
public static WatiN_IE eval(this WatiN_IE ie, string script)
{
return ie.eval(script, true);
}
public static WatiN_IE eval(this WatiN_IE ie, string script, bool waitForExecutionComplete)
{
var executionThread = O2Thread.staThread(()=> ie.IE.RunScript(script));
if (waitForExecutionComplete)
executionThread.Join();
return ie;
}
public static WatiN_IE alert(this WatiN_IE ie, string alertScript)
{
return ie.eval("alert({0});".format(alertScript));
}
public static object getJsObject(this WatiN_IE ie)
{
var toCSharpProxy = ie.injectJavascriptFunctions();
if (toCSharpProxy.notNull())
return toCSharpProxy.getJsObject();
return null;
}
public static T getJsObject<T>(this WatiN_IE ie, string jsCommand)
{
var jsObject = ie.getJsObject(jsCommand);
if (jsObject is T)
return (T)jsObject;
return default(T);
}
public static bool doesJsObjectExists(this WatiN_IE ie, string jsCommand)
{
var toCSharpProxy = ie.injectJavascriptFunctions();
if (toCSharpProxy.notNull())
{
var command = "window.external.setJsObject(typeof({0}))".format(jsCommand);
ie.invokeEval(command);
ie.remapInternalJsObject();
return toCSharpProxy.getJsObject().str()!="undefined";
}
return false;
}
public static object getJsVariable(this WatiN_IE ie, string jsCommand)
{
return ie.getJsObject(jsCommand);
}
public static object getJsObject(this WatiN_IE ie, string jsCommand)
{
var toCSharpProxy = ie.injectJavascriptFunctions();
if (toCSharpProxy.notNull())
{
var command = "window.external.setJsObject({0})".format(jsCommand);
ie.invokeEval(command);
ie.remapInternalJsObject();
return toCSharpProxy.getJsObject();
}
return null;
}
public static WatiN_IE remapInternalJsObject(this WatiN_IE ie)
{
//"setting JS _jsObject variable to getJsObject()".info();
ie.invokeEval("_jsObject = window.external.getJsObject()"); // creates JS variable to be used from JS
return ie;
}
public static WatiN_IE setJsObject(this WatiN_IE ie, object jsObject)
{
var toCSharpProxy = ie.injectJavascriptFunctions();
if (toCSharpProxy.notNull())
{
toCSharpProxy.setJsObject(jsObject);
ie.remapInternalJsObject();
}
return ie;
}
public static object waitForJsObject(this WatiN_IE watinIe)
{
return watinIe.waitForJsObject(500, 20);
}
public static object waitForJsObject(this WatiN_IE watinIe, int sleepMiliseconds, int maxSleepTimes)
{
"[WatiN_IE][waitForJsObject] trying to find jsObject for {0} x {1} ms".info(maxSleepTimes, sleepMiliseconds);
watinIe.setJsObject(null);
for(var i = 0; i < maxSleepTimes ; i++)
{
var jsObject = watinIe.getJsObject();
if(jsObject.notNull())
{
"[watinIe][waitForJsObject] got value: {0} (n tries)".info(jsObject, i);
return jsObject;
}
watinIe.sleep(500, false);
}
"[WatiN_IE][waitForJsObject] didn't find jsObject after {0} sleeps of {1} ms".error(maxSleepTimes, sleepMiliseconds);
return null;
}
public static object waitForJsVariable(this WatiN_IE watinIe, string jsCommand)
{
return watinIe.waitForJsVariable(jsCommand, 500, WatiN_IE_ExtensionMethods.WAITFORJSVARIABLE_MAXSLEEPTIMES);
}
public static object waitForJsVariable(this WatiN_IE watinIe, string jsCommand, int sleepMiliseconds, int maxSleepTimes)
{
"[WatiN_IE][waitForJsVariable] trying to find jsObject called '{0}' for {1} x {2} ms".info(jsCommand, maxSleepTimes, sleepMiliseconds);
watinIe.setJsObject(null);
for(var i = 0; i < maxSleepTimes ; i++)
{
if (watinIe.doesJsObjectExists(jsCommand))
{
var jsObject = watinIe.getJsObject(jsCommand);
"[watinIe][waitForJsVariable] got value: {0} ({1} tries)".info(jsObject, i);
return jsObject;
}
watinIe.sleep(500, false);
}
"[WatiN_IE][waitForJsVariable] didn't find jsObject called '{0}' after {1} sleeps of {2} ms".error(jsCommand, maxSleepTimes, sleepMiliseconds);
return null;
}
public static WatiN_IE deleteJsVariable(this WatiN_IE watinIe, string jsVariable)
{
var evalString = "try { delete " + jsVariable + " } catch(exception) { }";
watinIe.eval(evalString);
return watinIe;
}
}
}
See https://github.com/o2platform/FluentSharp_Fork.WatiN/tree/master/FluentSharp.WatiN/ExtensionMethods for many more WatiN/WebBroser Extension Methods