在WinForms/WPF WebBrowser控件中使用外部JavaScript文件

在WinForms/WPF WebBrowser控件中使用外部JavaScript文件,javascript,c#,wpf,Javascript,C#,Wpf,我在一个网站上发现了一个很酷的功能,它是用JavaScript实现的,我想在我的桌面应用程序中使用它(供个人使用)。 在我的实验中,我设法动态生成自定义HTML,使用webBrowser1.DocumentText=[my generated HTML] 我已经设法将一些内联JavaScript放入HTML中,并通过ScriptManager将其连接起来,这样我就可以从我的C#代码中调用JavaScript,向它传递一个值,并获得一个返回值 但我尝试使用的功能有点复杂:它不少于10个JavaSc

我在一个网站上发现了一个很酷的功能,它是用JavaScript实现的,我想在我的桌面应用程序中使用它(供个人使用)。 在我的实验中,我设法动态生成自定义HTML,使用
webBrowser1.DocumentText=[my generated HTML]
我已经设法将一些内联JavaScript放入HTML中,并通过ScriptManager将其连接起来,这样我就可以从我的C#代码中调用JavaScript,向它传递一个值,并获得一个返回值

但我尝试使用的功能有点复杂:它不少于10个JavaScript文件。其中2个是以通常的方式在网页中直接引用的

其他8个加载到其中一个脚本中:

var elem = document.createElement("script");
            elem.type = "text/javascript";
            elem.src = "/js/" + filename;
            document.body.appendChild(elem);
这8个文件实际上是数据文件,即使数据是用JavaScript表示的。它们相当大,每个都超过1MB。将所有内容都塞进HTML文件似乎相当愚蠢。此外,加载数据的脚本会创建一个“文件映射”,并进一步根据数据所在的文件引用数据:

  var fileMap = [
                        [/[\u0020-\u00ff]/, 'file1.js'],
                        [/[\u3000-\u30ff]/, 'file2.js'],
                        [/[\u4e00-\u5dff]/, 'file3.js'],
...
我不想求助于修改JavaScript,因为这不是我的强项。因此,浏览器需要“查看”js文件才能使用它们。我想在本地创建文件结构,并在那里导航浏览器。但我不希望我的解决方案中有任何松散的文件。如果可能的话,我想把所有的东西都嵌入进去。我怀疑我能否让浏览器导航到一个嵌入式资源,并将其他嵌入式资源视为文件。你知道我该怎么做吗

编辑:


我试着用本地文件做这件事。不走运。我可以正确加载HTML,但是当我尝试调用JavaScript调用时,什么都没有发生。我试着将浏览器指向那些js文件,以确保它们在那里。他们是。我尝试了一个带有src属性的元素,该元素指向与脚本文件位于同一子文件夹中的图像。它被渲染。就好像外部js文件拒绝加载一样。

我有一个与您的场景类似的需求,我使用嵌入在另外两个堆栈溢出答案中的两个关键点来解决它。正如SLaks的回答所指出的,第一个键使用语法
file://
作为指向外部文件的绝对路径的前缀。第二种方法是使用
.Replace(“\\”,“/”)
作为绝对文件路径,如Adam Plocher的回答和后续评论中所列

简而言之,HTML页面中每个外部文件的最终输出如下所示:

<link href="file:///c:/users/david/myApp/styles/site.css" rel="stylesheet" type="text/css">
2.声明绝对路径变量 注意:在上面的HTML页面中,我列出了一个
标记,其中声明的变量“absolutePath”设置为临时字符串。(在上面的HTML页面中,变量添加了一个全局变量,这不一定是最佳做法。您可以在命名空间中声明变量,而不是在全局命名空间中声明。)

3.修改延迟加载脚本以包含绝对路径变量 将“absolutePath”变量添加到JavaScript文件中,该变量延迟加载包含数据的其他JavaScript文件

elem.src = absolutePath + "/js/" + filename;
4.替换所有临时字符串实例的C#方法 在项目中,将以下行添加到表单加载事件处理程序中,或将此行放置在WebBrowser控件初始化中的某个位置

webBrowser1.DocumentText = GetUpdatedHtmlWithAbsolutePaths("/ReplaceWithAbsolutePath/", "HTMLPage1.html");
    private void Form1_Load(object sender, EventArgs e)
    {
        // Set the document text of the web browser control with the updated HTML
        webBrowser1.DocumentText = GetUpdatedHtmlWithAbsolutePaths("HTMLPage1.html");
    }
将以下方法添加到代码中。使用放置以下方法的类实例的名称更新对上一行中方法的调用

    // The result of this method will look like the following example:
    // <script src="file:///c:/users/david/documents/myApp/scripts/JavaScript1.js"></script>
    public string GetUpdatedHtmlWithAbsolutePaths(string tempPathString, string htmlFilename)
    {
        // Get the directory as the application
        // stackoverflow.com/questions/674857/should-i-use-appdomain-currentdomain-basedirectory-or-system-environment-current
        // Note that the 'BaseDirectory' property will return a string with trailing backslashes ('\\')
        string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
        // Replace '//' with '/' in the appDirectory string
        appDirectory = appDirectory.Replace("\\", "/");
        // Read all of the HTML text from the HTML page file
        string html = System.IO.File.ReadAllText(appDirectory + @"\" + htmlFilename);
        // Replace all '/ReplaceWithAbsolutePath/' strings within the HTML text with
        // the absolute path on the local machine
        html = html.Replace(tempPathString, "file:///" + appDirectory);
        return html;
    }
6.设置每个外部文件的“复制到输出目录” 如果您希望在解决方案/项目文件结构中包含外部文件,请查看Matthew Watson在此堆栈溢出中发布的答案

您可以将文件添加到项目中并选择其属性:“生成” 操作“作为“内容”和“复制到输出目录”作为“始终复制” 如果更新,则复制(后者更可取,否则 每次构建项目时,项目都会完全重建)

然后这些文件将被复制到您的输出文件夹

这比使用生成后步骤要好,因为VisualStudio将 知道这些文件是项目的一部分。(这会影响到 ClickOnce应用程序需要知道要将哪些文件添加到 单击一次数据。)

简而言之,将外部文件添加到项目中。您可以将外部文件夹添加到项目中的任何子文件夹中。(在Visual Studio 2013或2015中--我没有VS2012)在解决方案资源管理器中的外部文件上单击鼠标右键,然后从关联菜单中选择“属性”。将显示“属性”窗格。在“属性”窗格中,将“复制到输出目录”的设置更改为“始终复制”或“更新时复制”

使用视图源验证绝对路径字符串 运行您的项目,它将在WebBrowser控件中加载外部文件。假设尚未设置属性wbChartContainer.IsWebBrowserContextMenuEnabled=false在代码中或WebBrowser控件的属性窗格中,可以在窗体运行时右键单击WebBrowser控件。从关联菜单中单击“查看源”,并在“查看源”窗口中检查指向外部资源的路径

    // The result of this method will look like the following example:
    // <script src="file:///c:/users/david/documents/myApp/scripts/JavaScript1.js"></script>
    public string GetUpdatedHtmlWithAbsolutePaths(string tempPathString, string htmlFilename)
    {
        // Get the directory as the application
        // stackoverflow.com/questions/674857/should-i-use-appdomain-currentdomain-basedirectory-or-system-environment-current
        // Note that the 'BaseDirectory' property will return a string with trailing backslashes ('\\')
        string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
        // Replace '//' with '/' in the appDirectory string
        appDirectory = appDirectory.Replace("\\", "/");
        // Read all of the HTML text from the HTML page file
        string html = System.IO.File.ReadAllText(appDirectory + @"\" + htmlFilename);
        // Replace all '/ReplaceWithAbsolutePath/' strings within the HTML text with
        // the absolute path on the local machine
        html = html.Replace(tempPathString, "file:///" + appDirectory);
        return html;
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        // Set the document text of the web browser control with the updated HTML
        webBrowser1.DocumentText = GetUpdatedHtmlWithAbsolutePaths("HTMLPage1.html");
    }