簡體   English   中英

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

[英]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#方法中替換此臨時字符串。控制。

這是我的解決方案的基本步驟:

  1. 在HTML文件中為每個外部引用添加一個臨時字符串。
  2. 在HTML文件內的腳本標簽中聲明一個絕對路徑變量。 除非您要在JavaScript代碼中的其他地方使用絕對路徑,否則無需執行此步驟。 您的場景涉及延遲通過JavaScript代碼加載外部腳本文件,因此此步驟是必需的。
  3. 修改JavaScript代碼中的src屬性,該屬性會延遲使用絕對路徑變量加載其他腳本文件。
  4. 在您的應用程序中添加一個方法以將HTML頁面文件作為文本字符串加載,然后將所有臨時字符串實例替換為包含前綴“ file:///”的絕對路徑。 絕對路徑應帶有正斜杠。
  5. 將WebBrowser控件上的'DocumentText'屬性設置為更新的HTML。
  6. 將項目中每個外部文件的“復制到輸出目錄”設置為“始終復制”或“如果更新則復制”。 如果您的外部文件具有固定位置,並且該位置不在Visual Studio使用的生成或發布目錄中,則可能不需要此步驟。

以下是每個步驟的詳細信息。 我添加了很多細節,您可以跳過。 由於要對項目中的多個位置進行更改,因此我很樂意減少任何混亂。

1.使用臨時字符串

我使用了字符串“ / 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>

2.聲明絕對路徑變量

注意,在上面的HTML頁面中,我列出了<script>標記,其中已聲明的變量'absolutePath'設置為臨時字符串。 (在變量的上方HTML頁面中,添加了全局變量,但這不一定是最佳實踐。您可以在命名空間中聲明變量,而不是在全局命名空間中聲明變量。)

3.修改延遲加載腳本以包括絕對路徑變量

將'absolutePath'變量添加到您的JavaScript文件中,這會延遲加載包含您的數據的其他JavaScript文件。

elem.src = absolutePath + "/js/" + filename;

4.用C#方法替換所有臨時字符串實例

在您的項目中,將以下行添加到表單加載事件處理程序中,或將此行放置在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;
    }

5.設置WebBrowser控件的DocumentText屬性

我在表單加載事件處理程序中添加了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");
    }

6.設置每個外部文件的“復制到輸出目錄”

如果您希望外部文件包含在解決方案/項目文件結構中,請查看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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM