我在网站上发现了一个很酷的功能,用JavaScript实现,我想在我的桌面应用程序中使用它(供个人使用)。
在我的实验中,我设法动态生成自定义HTML,使用webBrowser1.DocumentText = [my generated HTML]
将其提供给浏览器
我已经设法将一些内联JavaScript放入HTML中,并通过ScriptManager将其连接起来,以便我可以从我的C#代码调用JavaScript,将值传递给它,并获得返回值。
但我试图使用的功能有点复杂:它不少于10个JavaScript文件。其中2个以常规方式<script src="/js/script1.js" type="text/javascript"></script>
其他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文件拒绝加载。
答案 0 :(得分:0)
我有与你的场景类似的需求,我使用嵌入在另外两个Stack Overflow答案中的两个关键点来解决它。正如SLaks&#39;所述。回答here第一个关键是使用语法file:///
作为外部文件的绝对路径的前缀。第二个是使用.Replace("\\", "/")
作为绝对文件路径,如Adam Plocher的答案中所列,以及他的一个后续评论here。
简而言之,HTML页面中每个外部文件的最终输出将如下所示:
<link href="file:///c:/users/david/myApp/styles/site.css" rel="stylesheet" type="text/css">
或
<script src="file:///c:/users/david/myApp/scripts/JavaScript1.js"></script>
在我的HTML文件中使用上面示例中的格式导致WebBrowser控件加载外部CSS,图像或脚本文件。
在上面第一个引用的SO答案的womd回答中,他使用方法System.IO.File.ReadAllText()
加载脚本文件并将脚本文件的文本嵌入到<head>
标记中。正如您在问题中指出的那样,直接将脚本文件加载到HTML页面中并不是您想要做的事情。
以下解决方案涉及使用相同的System.IO.File.ReadAllText()
方法,但会加载HTML页面的文本。该前提的工作方式类似于ASP.NET中的Razor View Engine。
下面的解决方案中的主要思想是在HTML页面中添加一个临时字符串,该页面将被加载到WebBrowser控件中,然后在HTML页面设置为加载之前在我的应用程序中的C#方法中替换此临时字符串进入WebBrowser控件。
以下是我的解决方案的基本步骤:
src
属性,该属性延迟使用绝对路径变量加载其他脚本文件。以下是每个步骤的详细信息。我添加了很多你可以跳过的细节。由于步骤对项目中的几个地方进行了更改,因此我很难减少任何混淆。
我使用了字符串&#34; / ReplaceWithAbsolutePath /&#34;但你可以使用任何不同的文字。 HTML页面中对外部文件的每个引用如下所示:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<link href="/ReplaceWithAbsolutePath/styles/site.css" rel="stylesheet" type="text/css">
<script type="text/javascript">
var absolutePath = "/ReplaceWithAbsolutePath/";
</script>
</head>
<body>
<p>My web page</p>
<script src="/ReplaceWithAbsolutePath/scripts/JavaScript1.js"></script>
</body>
</html>
请注意,在上面的HTML页面中,我列出了<script>
标记,其中包含声明的变量&#39; absolutePath&#39;设置为临时字符串。 (在上面的HTML页面中,变量添加了一个全局变量,这不一定是最佳实践。您可以在命名空间中声明变量,而不是在全局命名空间中声明它。)
添加&#39; absolutePath&#39;变量到您的JavaScript文件,延迟加载包含您的数据的其他JavaScript文件。
elem.src = absolutePath + "/js/" + filename;
在项目中,将以下行添加到表单加载事件处理程序中,或将此行放在WebBrowser控件初始化的某处。
webBrowser1.DocumentText = GetUpdatedHtmlWithAbsolutePaths("/ReplaceWithAbsolutePath/", "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;
}
我在表单加载事件处理程序中添加了WebBrowser控件的初始化,但当然,您可以添加在初始化WebBrowser控件的任何位置设置DocumentText属性的行。
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");
}
如果您希望外部文件包含在解决方案/项目文件结构中,请查看Matthew Watson在此Stack Overflow question中发布的答案。
您可以将文件添加到项目中并选择其属性:&#34;构建 动作&#34; as&#34;内容&#34;和&#34;复制到输出目录&#34; as&#34;始终复制&#34; 或者如果更新则复制(后者是优选的,因为否则 每次构建项目时都会完全重建项目。)
然后这些文件将被复制到您的输出文件夹。
这比使用后期构建步骤更好,因为Visual Studio会 知道这些文件是项目的一部分。 (这会影响像 ClickOnce应用程序需要知道要添加到哪些文件 clickonce data。)
简而言之,将外部文件添加到项目中。您可以将外部添加到项目中的任何子文件夹。 (在Visual Studio 2013或2015中 - 我没有VS2012)在解决方案资源管理器中右键单击外部文件,然后从上下文菜单中选择“属性”。将显示“属性”窗格。在“属性”窗格中,更改“复制到输出目录”的设置。到&#39;永远复制&#39;或者&#39;复制如果更新&#39;。
运行您的项目,它应该在WebBrowser控件中加载您的外部文件。假设您尚未在代码或“属性”窗格中为WebBrowser控件设置属性wbChartContainer.IsWebBrowserContextMenuEnabled = false;
,则可以在窗体运行时右键单击WebBrowser控件。点击查看来源&#39;从上下文菜单中,在“查看源”窗口中检查外部资源的路径。