NanUI文档 – 如何实现C#与Javascript的交互通信

NanUI文档目录

  • NanUI简介
  • 开头利用NanUI
  • 卷入并采用内嵌式的HTML/CSS/JS资源
  • 利用网页来计划总体窗口
  • 怎么实现C#暨Javascript的并行通信
  • 怎处理NanUI中之下载过程 – DonwloadHandler的行使(待更新。。。)
  • 如何处理NanUI中的弹窗过程 – LifeSpanHandler的用(待更新。。。)
  • 哪决定Javascript对话框 – JsDialogHandler的使(待更新。。。)
  • 于定义资源处理程序 (待更新。。。)

安落实C#及Javascript的竞相通信

经过事先的章,相信您曾经对NanUI有了起来的刺探。但到目前为止,我们采用NanUI仅仅只是作为呈现HTML界面的器皿,并未提到CEF与C#其间数的互动。那么本文将略介绍如何以NanUI中使用C#调用Javascript的函数和哪当Javascript注入C#的对象、属性与法。

C#调用Javascript函数

勿欲取返回值的景况

倘页面中若下Javascript的函数sayHello,它的企图是于DOM中创造一个暗含有“Hello
NanUI!”字样的p元素。

function sayHello() {
    var p = document.createElement("p");
    p.innerText = "Hello NanUI!";

    var container = document.getElementById("hello-container");
    container.appendChild(p);
}

示范中,该函数并无在Javascript环境里调用,而是在页面加载成功后用NanUI的ExecuteJavascript主意来调动用它们。ExecuteJavascript术执行的回结果也一个bool类型,它指示了这次发生没有发出成执行。

于窗体的构造函数中,通过注册Formium的LoadHandler中之OnLoadEnd事件来监测页面加载成功的景,并当页面加载成功后调用JS环境遭受的函数sayHello。

namespace CommunicateBetweenJsAndCSharp
{
    using NetDimension.NanUI;
    public partial class Form1 : Formium
    {
        public Form1()
            : base("http://res.app.local/www/index.html",false)
        {
            InitializeComponent();

            LoadHandler.OnLoadEnd += LoadHandler_OnLoadEnd;
        }

        private void LoadHandler_OnLoadEnd(object sender, Chromium.Event.CfxOnLoadEndEventArgs e)
        {
            // Check if it is the main frame when page has loaded.
            if(e.Frame.IsMain)
            {
                ExecuteJavascript("sayHello()");
            }
        }
    }
}

运作后,可以看来界面被显了“Hello
NanUI!”字样,说明使用ExecuteJavascript能够调用JS函数。


亟需取得返回值的情形

点的例子中经ExecuteJavascript方法来成调用了JS环境中之函数。但容易发现,这种调用方式C#举凡不曾接受到其他返回值的。但骨子里的类别里,我们是需要由JS环境获得到返回值的,这时候使用ExecuteJavascript以不克满足急需,使用另外一个智EvaluateJavascript得帮助我们由JS环境中拿走JS函数的回值。

要是发生另外一个Javascript函数sayHelloToSomeone,它亦可收到一个字符传参数,在部数体中拼接并返拼接后的字符串。

function sayHelloToSomeone(who) {
    return "Hello " + who + "!";
}

一律的,在方例子LoadHandler的OnLoadEnd事件中我们来推行sayHelloToSomeone,并通过C#传送参数并获拼接后的归值。EvaluateJavascript艺术通过一个回调Action来取得JS环境中之回值。这个Action有个别个参数,第一单凡是返回值的联谊,第二独凡是JS环境之好对象,如果函数正确执行,那么第二只参数为null

namespace CommunicateBetweenJsAndCSharp
{
    using NetDimension.NanUI;
    public partial class Form1 : Formium
    {
        public Form1()
            : base("http://res.app.local/www/index.html",false)
        {
            InitializeComponent();

            LoadHandler.OnLoadEnd += LoadHandler_OnLoadEnd;
        }

        private void LoadHandler_OnLoadEnd(object sender, Chromium.Event.CfxOnLoadEndEventArgs e)
        {
            // Check if it is the main frame when page has loaded.
            if(e.Frame.IsMain)
            {
                EvaluateJavascript("sayHelloToSomeone('C#')", (value, exception) =>
                {
                    if(value.IsString)
                    {
                        // Get value from Javascript.
                        var jsValue = value.StringValue;

                        MessageBox.Show(jsValue);
                    }
                });
            }
        }
    }
}

于地方的示范中,通过我们可肯定掌握JS函数sayHelloToSomeone的返回值一定为String类型,因此于C#的回调中一直使用Value的StringValue属性来赢得JS函数的字符传返回值。但每当实际上的采用中,有或连无了明了返回值的品种,因此要用Value中置的各个判断属性来挨家挨户筛选返回值。

得小心的是,Value的近乎是凡ChromiumFX中之CfrV8Value路,它是一个良重要的门类,基本上所有在C#以及CEF间的通信都是由这类型来完成的。


Javascript调用C#对象与办法

粗略的下示范

上面的篇章中示范了何等用C#来调用Javascript中之函数,那么下的内容将介绍如何使用Javascript来调用C#惨遭之靶子、属性和各种措施。

在此之前,需要介绍NanUI窗体基类Formium遭受的显要性质GlobalObject,您可管他知道成Javascript环境面临的window靶。如果你要在Javascript环境下使用C#着之各种对象、属性和方式,都亟待以这些目标、属性、方法注册到GlobalObject里。

下的例子,通过当Form1的构造函数中注册一个号称吧my的JS对象,并在my停放一个止读属性name,以及showCSharpMessageBoxgetArrayFromCSharpgetObjectFromCSharp其三只函数。

//register the "my" object
var myObject = GlobalObject.AddObject("my");

//add property "name" to my, you should implemnt the getter/setter of name property by using PropertyGet/PropertySet events.
var nameProp = myObject.AddDynamicProperty("name");
nameProp.PropertyGet += (prop, args) =>
{
    // getter - if js code "my.name" executes, it'll get the string "NanUI". 
    args.Retval = CfrV8Value.CreateString("NanUI");
    args.SetReturnValue(true);
};
nameProp.PropertySet += (prop, args) =>
{
    // setter's value from js context, here we do nothing, so it will store or igrone by your mind.
    var value = args.Value;
    args.SetReturnValue(true);
};


//add a function showCSharpMessageBox
var showMessageBoxFunc = myObject.AddFunction("showCSharpMessageBox");
showMessageBoxFunc.Execute += (func, args) =>
{
    //it will be raised by js code "my.showCSharpMessageBox(`some text`)" executed.
    //get the first string argument in Arguments, it pass by js function.
    var stringArgument = args.Arguments.FirstOrDefault(p => p.IsString);

    if (stringArgument != null)
    {
        MessageBox.Show(this, stringArgument.StringValue, "C# Messagebox", MessageBoxButtons.OK, MessageBoxIcon.Information);


    }
};

//add a function getArrayFromCSharp, this function has an argument, it will combind C# string array with js array and return to js context.
var friends = new string[] { "Mr.JSON", "Mr.Lee", "Mr.BONG" };

var getArrayFromCSFunc = myObject.AddFunction("getArrayFromCSharp");

getArrayFromCSFunc.Execute += (func, args) =>
{
    var jsArray = args.Arguments.FirstOrDefault(p => p.IsArray);



    if (jsArray == null)
    {
        jsArray = CfrV8Value.CreateArray(friends.Length);
        for (int i = 0; i < friends.Length; i++)
        {
            jsArray.SetValue(i, CfrV8Value.CreateString(friends[i]));
        }
    }
    else
    {
        var newArray = CfrV8Value.CreateArray(jsArray.ArrayLength + friends.Length);

        for (int i = 0; i < jsArray.ArrayLength; i++)
        {
            newArray.SetValue(i, jsArray.GetValue(i));
        }

        var jsArrayLength = jsArray.ArrayLength;

        for (int i = 0; i < friends.Length; i++)
        {
            newArray.SetValue(i + jsArrayLength, CfrV8Value.CreateString(friends[i]));
        }


        jsArray = newArray;
    }


    //return the array to js context

    args.SetReturnValue(jsArray);

    //in js context, use code "my.getArrayFromCSharp()" will get an array like ["Mr.JSON", "Mr.Lee", "Mr.BONG"]
};

//add a function getObjectFromCSharp, this function has no arguments, but it will return a Object to js context.
var getObjectFormCSFunc = myObject.AddFunction("getObjectFromCSharp");
getObjectFormCSFunc.Execute += (func, args) =>
{
    //create the CfrV8Value object and the accssor of this Object.
    var jsObjectAccessor = new CfrV8Accessor();
    var jsObject = CfrV8Value.CreateObject(jsObjectAccessor);

    //create a CfrV8Value array
    var jsArray = CfrV8Value.CreateArray(friends.Length);

    for (int i = 0; i < friends.Length; i++)
    {
        jsArray.SetValue(i, CfrV8Value.CreateString(friends[i]));
    }

    jsObject.SetValue("libName", CfrV8Value.CreateString("NanUI"), CfxV8PropertyAttribute.ReadOnly);
    jsObject.SetValue("friends", jsArray, CfxV8PropertyAttribute.DontDelete);


    args.SetReturnValue(jsObject);

    //in js context, use code "my.getObjectFromCSharp()" will get an object like { friends:["Mr.JSON", "Mr.Lee", "Mr.BONG"], libName:"NanUI" }
};

运作品种开辟CEF的DevTools窗口,在Console中输入my,就会见到my对象的详细信息。

亚洲必赢bwin696.com 1

执行my.showCSharpMessageBox(“SOME TEXT FROM
JS”)
命令,将调用C#的MessageBox来具体JS函数中提供的“SOME TEXT FROM
JS”字样。

执行my.getArrayFromCSharp()能够从C#蒙得到我们放开的字符串数组中之老三只字符串。如果当函数中指定了一个数组作为参数,那么指定的之数组将和C#的字符串数组合并。

> my.getArrayFromCSharp()
["Mr.JSON", "Mr.Lee", "Mr.BONG"]

> my.getArrayFromCSharp(["Js_Bison", "Js_Dick"])
["Js_Bison", "Js_Dick", "Mr.JSON", "Mr.Lee", "Mr.BONG"]

执行my.getObjectFromCSharp()能够从C#回来我们拼装的靶子,该对象来一个字符型的libName性,以及一个字符串数组friends

> my.getObjectFromCSharp()
Object {libName: "NanUI", friends: Array(3)}

反过来调函数

拨调函数是Javascript里面要和常用之作用,如果你当JS环境被登记之道有函数型的参数(即回调函数),通过Execute事件的Arguments可以赢得回调的function,并使用CfrV8Value底ExecuteFunction来执行回调。

//add a function with callback function

var callbackTestFunc = GlobalObject.AddFunction("callbackTest");
callbackTestFunc.Execute += (func,args)=> {
    var callback = args.Arguments.FirstOrDefault(p => p.IsFunction);
    if(callback != null)
    {
        var callbackArgs = CfrV8Value.CreateObject(new CfrV8Accessor());
        callbackArgs.SetValue("success", CfrV8Value.CreateBool(true), CfxV8PropertyAttribute.ReadOnly);
        callbackArgs.SetValue("text", CfrV8Value.CreateString("Message from C#"), CfxV8PropertyAttribute.ReadOnly);

        callback.ExecuteFunction(null, new CfrV8Value[] { callbackArgs });
    }
};

在Console中执行callbackTest(function(result){ console.log(result);
})
用推行匿名回调,并得到到C#回传的result对象。

> callbackTest(function(result){ console.log(result); })
Object {success: true, text: "Message from C#"}

在大部情下,在Javascript中回调都是为实施了片异步的操作,那么要这些异步的操作是以C#实行吗是实用的,只是实现起来就是比较复杂。下面将演示如何贯彻一个异步回调。

//add a function with async callback
var asyncCallbackTestFunc = GlobalObject.AddFunction("asyncCallbackTest");
asyncCallbackTestFunc.Execute += async (func, args) => {
//save current context
var v8Context = CfrV8Context.GetCurrentContext();
var callback = args.Arguments.FirstOrDefault(p => p.IsFunction);

//simulate async methods.
await Task.Delay(5000);

if (callback != null)
{
    //get render process context
    var rc = callback.CreateRemoteCallContext();

    //enter render process
    rc.Enter();

    //create render task
    var task = new CfrTask();
    task.Execute += (_, taskArgs) =>
    {
        //enter saved context
        v8Context.Enter();

        //create callback argument
        var callbackArgs = CfrV8Value.CreateObject(new CfrV8Accessor());
        callbackArgs.SetValue("success", CfrV8Value.CreateBool(true), CfxV8PropertyAttribute.ReadOnly);
        callbackArgs.SetValue("text", CfrV8Value.CreateString("Message from C#"), CfxV8PropertyAttribute.ReadOnly);

        //execute callback
        callback.ExecuteFunction(null, new CfrV8Value[] { callbackArgs });


        v8Context.Exit();

        //lock task from gc
        lock (task)
        {
            Monitor.PulseAll(task);
        }
    };

    lock (task)
    {
        //post task to render process
        v8Context.TaskRunner.PostTask(task);
    }

    rc.Exit();

    GC.KeepAlive(task);
}

在Console中执行asyncCallbackTest(function(result){
console.log(result);
})
将执行匿名回调,大约5秒后收获到C#回传的result对象。

> asyncCallbackTest(function(result){ console.log(result); })
Object {success: true, text: "Message from C#"}

如上,您曾经略询问了利用NanUI如何做到C#和Javascript的互动通信。NanUI基被开源项目ChromiumFX开发,因此C#跟Javascript的互相和ChomiumFX保持一致,如果要开销尤其错综复杂的效果,请自行检索以及参照ChromiumFX的连带API及示范。

以身作则源码

git clone https://github.com/NetDimension/NanUI-Examples-04-Communicate-Between-CSharp-And-JS.git

社群和援助

GitHub
https://github.com/NetDimension/NanUI/

交流群QQ群
521854872

救助作者

若是您喜爱我之做事,并且愿意NanUI持续的开拓进取,请对NanUI项目展开资助为这个来鼓励和支持我连续NanUI的开销工作。你可行使微信或者支付宝来围观下的亚维码进行资助。

亚洲必赢bwin696.com 2

相关文章