日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

NanUI文档 - 如何实现C#与Javascript的相互通信

發布時間:2023/12/10 C# 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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對象的詳細信息。

執行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 functionvar 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

轉載于:https://www.cnblogs.com/Jeely/p/11077397.html

總結

以上是生活随笔為你收集整理的NanUI文档 - 如何实现C#与Javascript的相互通信的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。