【问题标题】:How should an array be passed to a Javascript function from C#?数组应该如何从 C# 传递给 Javascript 函数?
【发布时间】:2011-09-30 23:40:56
【问题描述】:

我使用 WPF 中的 WebBrowser 对象,并在浏览器中加载的页面中调用一些 Javascript 代码,如下所示:

myWebBrowser.InvokeScript("myJsFunc", new object[] { foo.Text, bar.ToArray<string>()});

现在,js 函数应该遍历第二个参数(字符串数组)的元素并做相应的事情。唯一的问题是参数好像不是作为js数组传递的。

例如,

alert(typeof theArray);

警报“未知”。

从 CSharp 调用 js 函数时,将数组作为参数传递的正确方法是什么?

【问题讨论】:

  • 请记住,typeof [] == 'object'.
  • 我很难从这样的物体中取出任何有用的东西。 typeof problemArrayunknown,不可能遍历它的字段。
  • 尝试将所有项目连接成一个以 ; 分隔的字符串或 |例如,然后在 javascript 中,将其拆分回数组

标签: c# javascript webbrowser-control


【解决方案1】:

也许将它作为json字符串传递并在js函数中解析它

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var json = serializer.Serialize(bar.ToArray<string>());

myWebBrowser.InvokeScript("myJsFunc", new object[] { foo.Text, json });

js:

function myJsFunc(json) {
   var data = JSON.parse(json);
   // do something with it.
}

http://blogs.microsoft.co.il/blogs/pini_dayan/archive/2009/03/12/convert-objects-to-json-in-c-using-javascriptserializer.aspx

【讨论】:

    【解决方案2】:

    它本身并不能解决问题,但如果您只有一个数组要传递,它就可以解决问题:您可以向 JavaScript 函数发送任意数量的参数,并通过 arguments 特殊变量访问它们。它变得类似于接受可变数量参数的函数,具有相同的优点和问题(例如,您必须最后传递数组,如前所述,您只能传递一个)。

    这是一个示例 JavaScript 函数:

    function foo()
    {
        var stringArgs = [];
        for (var i = 0; i < arguments.length; i++)
            stringArgs.push(arguments[i]);
    
        // do stuff with stringArgs
    }
    

    你可以像这样从 C# 中调用它:

    List<string> arguments = new List<string>();
    arguments.Add("foo");
    arguments.Add("bar");
    webBrowser.InvokeScript("foo", arguments.ToArray());
    

    【讨论】:

      【解决方案3】:

      如果你真的想从代码中榨取每一点性能,你可以通过 javascript 中的 eval 来避免反序列化。这个概念是像这样构造调用:

      ((IHTMLWindow2)webBrowserControl.Document.Window.DomWindow).execScript("var returnValue = someFunction([ 'abc', 'xyz', '1', '2', '3' ], { foo: 'xyz', bar: 1 });"
      

      请注意,我们使用的 .execScript 让世界变得与众不同。这是因为 .InvokeScript 会强制使用基于 string 的参数(这会迫使您在 javascript 端使用 eval)来强制输入 javascript 方法,而 .execScript() 使我们能够编写任意javascript 代码,包括您在上面看到的内容(请注意,参数是一个显式的 javascript 数组和一组属性)。现在我们可以直接编码数组和对象并将它们写为参数。为此,我们只需使用 Newtonsoft.Json 来序列化数组和对象:

      class Test {
           public string foo;
           public int bar;
      }
      ((IHTMLWindow2)webBrowserControl.Document.Window.DomWindow).execScript("var returnValue = someFunction(" +
      JsonConvert.SerializeObject((new List<object>(2) { "abc", "xyz", 1, 2, 3 }).ToArray()) + ", " + JsonConvert.SerializeObject(new Test() { foo = "xyz", bar = 1 }) + ");");
      

      另一件事是检索结果返回值:

      string result = (string)webBrowserControl.Document.InvokeScript("eval", new object[] { @"returnValue;" }));
      

      为方便起见,您可能需要编写一个实用方法,该方法迭代给定参数并正确序列化它们,调用函数,然后检索返回值。

      【讨论】:

      • execScript 在 IE11 之前是一个不错的选择。从IE11开始不支持,所以msdn suggests using eval as a replacement
      • @anikiforov 你是绝对正确的。 execScript 被标记为已弃用很长时间。然后在 IE11 的一些更新中突然杀死了它,没有任何事先警告代表 MS。然后许多开发人员抱怨 COM 的功能丢失。然后 MS 发布了另一个更新,允许再次在 COM 上使用 .execScript(但该方法在 javascript 中不再可用 - 您可以使用完全更新的 IE11+ 中的开发工具验证它)。真是一团糟。
      【解决方案4】:

      你需要先将数组转换成JS数组,如下所示:

      ["John", "Bob", "Sue"] // literal array
      

      以下两个例子:

      StringBuilder sb = new StringBuilder();
      string[] stringArray = bar.ToArray<string>();
      
      //Build the JS array.
      sb.Append( "[");
      for (int i = 0; i < stringArray.Length; i++)
      {
          sb.AppendFormat( "'{0}', ", stringArray[i] );
      
      }
      sb.Append( "]");
      
      
      // Now send the array to the JS function.
      myWebBrowser.InvokeScript("myJsFunc", new object[] { foo.Text, sb.ToString() });
      

      您可能还想删除尾随。不要忘记为StringBuilder导入相应的库,我认为是System.Text.StringBuilder;

      或使用,示例二:

      string[] stringArray = bar.ToArray<string>();
      
      // or simpler to use string join.
      string jsArray = "[" + String.Join( ",", stringArray ) + "]";
      //
      myWebBrowser.InvokeScript("myJsFunc", new object[] { foo.Text, jsArray });
      

      【讨论】:

      • 传递这个字符串结构,在JavaScript端自动得到一个数组,还是需要eval呢?
      • 它应该自动被视为一个字符串是JavaScript,所以你只需在JavaScript函数中处理它。见这里JS Arrays
      • 如果要显示为字符串,那么人们不妨使用 JavaScriptSerializer 类来支持各种对象。
      猜你喜欢
      • 1970-01-01
      • 2012-02-10
      • 1970-01-01
      • 2016-11-05
      • 2012-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多