[英]Using external JavaScript files in a WinForms/WPF WebBrowser control
我在一個用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文件拒絕加載一樣。
我有與您的方案類似的需求,並且使用其他兩個Stack Overflow答案中嵌入的兩個要點解決了該問題。 正如SLaks的回答指出這里的第一個關鍵是使用語法file:///
作為前綴到外部文件的絕對路徑。 第二種方法是使用.Replace("\\\\", "/")
作為絕對文件路徑,如Adam Plocher的回答及其此處的后續評論之一所示。
簡而言之,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頁面設置為加載到WebBrowser中之前,在我的應用程序的C#方法中替換此臨時字符串。控制。
這是我的解決方案的基本步驟:
src
屬性,該屬性會延遲使用絕對路徑變量加載其他腳本文件。 以下是每個步驟的詳細信息。 我添加了很多細節,您可以跳過。 由於要對項目中的多個位置進行更改,因此我很樂意減少任何混亂。
我使用了字符串“ / ReplaceWithAbsolutePath /”,但是您可以使用任何不同的文本。 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>
標記,其中已聲明的變量'absolutePath'設置為臨時字符串。 (在變量的上方HTML頁面中,添加了全局變量,但這不一定是最佳實踐。您可以在命名空間中聲明變量,而不是在全局命名空間中聲明變量。)
將'absolutePath'變量添加到您的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 問題中發布的答案。
您可以將文件添加到項目中並選擇其屬性:“構建操作”作為“內容”,“復制到輸出目錄”作為“始終復制”或“如果較新則復制”(后者是可取的,因為否則每次您都完全重建項目時,構建它)。
然后,這些文件將被復制到您的輸出文件夾。
這比使用后期構建步驟更好,因為Visual Studio會知道文件是項目的一部分。 (這會影響諸如ClickOnce應用程序之類的應用程序,這些應用程序需要知道要將哪些文件添加到clickonce數據中。)
簡而言之,將外部文件添加到您的項目中。 您可以將外部添加到項目中的任何子文件夾中。 (在Visual Studio 2013或2015中-我沒有VS2012)在解決方案資源管理器中右鍵單擊外部文件,然后從上下文菜單中選擇“屬性”。 將顯示“屬性”窗格。 在“屬性”窗格中,將“復制到輸出目錄”的設置更改為“始終復制”或“如果更新則復制”。
運行您的項目,它將在WebBrowser控件中加載您的外部文件。 假設您尚未設置屬性wbChartContainer.IsWebBrowserContextMenuEnabled = false;
在代碼中或WebBrowser控件的“屬性”窗格中,可以在運行表單時右鍵單擊WebBrowser控件。 從上下文菜單中單擊“查看源代碼”,然后在“查看源代碼”窗口中檢查到您的外部資源的路徑。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.