Sdílet prostřednictvím


HybridWebView

Rozhraní .NET Multi-Platform App UI (.NET MAUI) HybridWebView umožňuje hostování libovolného obsahu HTML/JS/CSS ve webovém zobrazení a umožňuje komunikaci mezi kódem ve webovém zobrazení (JavaScript) a kódem, který je hostitelem webového zobrazení (C#/.NET). Pokud máte například existující aplikaci React JS, můžete ji hostovat v nativní aplikaci .NET MAUI pro různé platformy a vytvořit back-end aplikace pomocí C# a .NET.

HybridWebView definuje následující vlastnosti:

  • DefaultFile, typu string?, který určuje soubor v rámci HybridRoot , který má být sloužit jako výchozí soubor. Výchozí hodnota je index.html.
  • HybridRoot, typu string?, což je cesta v rámci nezpracovaných prostředků aplikace, které obsahují obsah webové aplikace. Výchozí hodnota je wwwroot, která se mapuje na Resources/Raw/wwwroot.

Kromě toho definuje RawMessageReceived událost, HybridWebView která se vyvolá při přijetí nezpracované zprávy. Objekt HybridWebViewRawMessageReceivedEventArgs , který doprovází událost, definuje Message vlastnost, která obsahuje zprávu.

Kód jazyka C# vaší aplikace může vyvolat synchronní a asynchronní javascriptové metody v rámci HybridWebView metod InvokeJavaScriptAsync a EvaluateJavaScriptAsync metod. Další informace najdete v tématu Volání JavaScriptu z jazyka C#.

K vytvoření aplikace HybridWebView .NET MAUI potřebujete:

  • Webový obsah aplikace, který se skládá ze statického HTML, JavaScriptu, CSS, obrázků a dalších souborů.
  • Ovládací HybridWebView prvek jako součást uživatelského rozhraní aplikace. Toho lze dosáhnout tak, že na ni odkazujete v kódu XAML aplikace.
  • Kód ve webovém obsahu a v jazyce C#/.NET, který používá HybridWebView rozhraní API k odesílání zpráv mezi dvěma komponentami.

Celá aplikace, včetně webového obsahu, je zabalená a běží místně na zařízení a je možné ji publikovat do příslušných obchodů s aplikacemi. Webový obsah je hostovaný v nativním ovládacím prvku webového zobrazení a běží v kontextu aplikace. Každá část aplikace má přístup k externím webovým službám, ale nevyžaduje se.

Vytvoření aplikace .NET MAUI HybridWebView

Vytvoření aplikace .NET MAUI pomocí HybridWebView:

  1. Otevřete existující projekt aplikace .NET MAUI nebo vytvořte nový projekt aplikace .NET MAUI.

  2. Přidejte webový obsah do projektu aplikace .NET MAUI.

    Webový obsah vaší aplikace by měl být součástí projektu .NET MAUI jako nezpracované prostředky. Nezpracovaný prostředek je libovolný soubor ve složce Resources\Raw aplikace a obsahuje podsložky. U výchozího HybridWebViewwebového obsahu by měl být umístěn ve složce Resources\Raw\wwwroot s hlavním souborem s názvem index.html.

    Jednoduchá aplikace může mít následující soubory a obsah:

    • Resources\Raw\wwwroot\index.html s obsahem pro hlavní uživatelské rozhraní:

      <!DOCTYPE html>
      
      <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
      <head>
          <meta charset="utf-8" />
          <title></title>
          <link rel="icon" href="data:,">
          <script src="scripts/HybridWebView.js"></script>
          <script>
              window.addEventListener(
                  "HybridWebViewMessageReceived",
                  function (e) {
                      var messageFromCSharp = document.getElementById("messageFromCSharp");
                      messageFromCSharp.value += '\r\n' + e.detail.message;
                  });
          </script>
      </head>
      <body>
          <h1>HybridWebView app!</h1>
          <div>
              <button onclick="window.HybridWebView.SendRawMessage('Message from JS!')">Send message to C#</button>
          </div>
          <div>
              Messages from C#: <textarea readonly id="messageFromCSharp" style="width: 80%; height: 300px;"></textarea>
          </div>
      </body>
      </html>
      
    • Resources\Raw\wwwroot\scripts\HybridWebView.js se standardní HybridWebView knihovnou JavaScriptu:

      window.HybridWebView = {
          "Init": function () {
              function DispatchHybridWebViewMessage(message) {
                  const event = new CustomEvent("HybridWebViewMessageReceived", { detail: { message: message } });
                  window.dispatchEvent(event);
              }
      
              if (window.chrome && window.chrome.webview) {
                  // Windows WebView2
                  window.chrome.webview.addEventListener('message', arg => {
                      DispatchHybridWebViewMessage(arg.data);
                  });
              }
              else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
                  // iOS and MacCatalyst WKWebView
                  window.external = {
                      "receiveMessage": message => {
                          DispatchHybridWebViewMessage(message);
                      }
                  };
              }
              else {
                  // Android WebView
                  window.addEventListener('message', arg => {
                      DispatchHybridWebViewMessage(arg.data);
                  });
              }
          },
      
          "SendRawMessage": function (message) {
              window.HybridWebView.__SendMessageInternal('RawMessage', message);
          },
      
          "__SendMessageInternal": function (type, message) {
      
              const messageToSend = type + '|' + message;
      
              if (window.chrome && window.chrome.webview) {
                  // Windows WebView2
                  window.chrome.webview.postMessage(messageToSend);
              }
              else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
                  // iOS and MacCatalyst WKWebView
                  window.webkit.messageHandlers.webwindowinterop.postMessage(messageToSend);
              }
              else {
                  // Android WebView
                  hybridWebViewHost.sendMessage(messageToSend);
              }
          },
      
          "InvokeMethod": function (taskId, methodName, args) {
              if (methodName[Symbol.toStringTag] === 'AsyncFunction') {
                  // For async methods, we need to call the method and then trigger the callback when it's done
                  const asyncPromise = methodName(...args);
                  asyncPromise
                      .then(asyncResult => {
                          window.HybridWebView.__TriggerAsyncCallback(taskId, asyncResult);
                      })
                      .catch(error => console.error(error));
              } else {
                  // For sync methods, we can call the method and trigger the callback immediately
                  const syncResult = methodName(...args);
                  window.HybridWebView.__TriggerAsyncCallback(taskId, syncResult);
              }
          },
      
          "__TriggerAsyncCallback": function (taskId, result) {
              // Make sure the result is a string
              if (result && typeof (result) !== 'string') {
                  result = JSON.stringify(result);
              }
      
              window.HybridWebView.__SendMessageInternal('InvokeMethodCompleted', taskId + '|' + result);
          }
      }
      
      window.HybridWebView.Init();
      

    Pak do projektu přidejte libovolný další webový obsah.

    Upozorňující

    V některých případech může Visual Studio přidat položky do souboru .csproj projektu, které jsou nesprávné. Při použití výchozího umístění pro nezpracované prostředky by neměly být žádné položky pro tyto soubory nebo složky v souboru .csproj .

  3. HybridWebView Přidejte ovládací prvek do aplikace:

    <Grid RowDefinitions="Auto,*"
          ColumnDefinitions="*">
        <Button Text="Send message to JavaScript"
                Clicked="OnSendMessageButtonClicked" />
        <HybridWebView x:Name="hybridWebView"
                       RawMessageReceived="OnHybridWebViewRawMessageReceived"
                       Grid.Row="1" />
    </Grid>
    
  4. HybridWebView Pomocí rozhraní API můžete odesílat zprávy mezi kódem JavaScriptu a jazyka C#:

    private void OnSendMessageButtonClicked(object sender, EventArgs e)
    {
        hybridWebView.SendRawMessage($"Hello from C#!");
    }
    
    private async void OnHybridWebViewRawMessageReceived(object sender, HybridWebViewRawMessageReceivedEventArgs e)
    {
        await DisplayAlert("Raw Message Received", e.Message, "OK");
    }
    

    Výše uvedené zprávy jsou klasifikovány jako nezpracované, protože se neprovádí žádné další zpracování. Můžete také zakódovat data ve zprávě, aby bylo možné provádět pokročilejší zasílání zpráv.

Vyvolání JavaScriptu z jazyka C#

Kód jazyka C# vaší aplikace může synchronně a asynchronně vyvolat javascriptové metody v rámci , HybridWebViews volitelnými parametry a volitelnou návratovou hodnotou. Toho lze dosáhnout pomocí InvokeJavaScriptAsync a EvaluateJavaScriptAsync metod:

  • Metoda EvaluateJavaScriptAsync spustí kód JavaScriptu zadaný prostřednictvím parametru a vrátí výsledek jako řetězec.
  • Metoda InvokeJavaScriptAsync vyvolá zadanou javascriptovou metodu, volitelně předává hodnoty parametrů a určuje obecný argument, který označuje typ návratové hodnoty. Vrátí objekt obecného typu argumentu, který obsahuje návratovou hodnotu volanou javascriptovou metodu. Interně jsou parametry a návratové hodnoty kódované ve formátu JSON.

Vyvolání synchronního JavaScriptu

Synchronní javascriptové metody lze vyvolat pomocí EvaluateJavaScriptAsync metod a InvokeJavaScriptAsync metod. V následujícím příkladu InvokeJavaScriptAsync se metoda používá k předvedení vyvolání JavaScriptu, který je vložený do webového obsahu aplikace. Například jednoduchá javascriptová metoda pro přidání dvou čísel může být definována ve webovém obsahu:

function AddNumbers(a, b) {
    return a + b;
}

Metodu AddNumbers JavaScriptu je možné vyvolat z jazyka InvokeJavaScriptAsync C#:

double x = 123d;
double y = 321d;

double result = await hybridWebView.InvokeJavaScriptAsync<double>(
    "AddNumbers", // JavaScript method name
    HybridSampleJSContext.Default.Double, // JSON serialization info for return type
    [x, y], // Parameter values
    [HybridSampleJSContext.Default.Double, HybridSampleJSContext.Default.Double]); // JSON serialization info for each parameter

Vyvolání metody vyžaduje zadání JsonTypeInfo objektů, které obsahují informace o serializaci pro typy použité v operaci. Tyto objekty se automaticky vytvářejí zahrnutím následující partial třídy do projektu:

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(double))]
internal partial class HybridSampleJsContext : JsonSerializerContext
{
    // This type's attributes specify JSON serialization info to preserve type structure
    // for trimmed builds.
}

Důležité

HybridSampleJsContext Třída musí být partial tak, aby generování kódu mohla poskytnout implementaci při kompilaci projektu. Pokud je typ vnořený do jiného typu, musí být partialtento typ také .

Vyvolání asynchronního JavaScriptu

Asynchronní javascriptové metody lze vyvolat pomocí EvaluateJavaScriptAsync metod a InvokeJavaScriptAsync metod. V následujícím příkladu InvokeJavaScriptAsync se metoda používá k předvedení vyvolání JavaScriptu, který je vložený do webového obsahu aplikace. Například javascriptová metoda, která asynchronně načítá data, by mohla být definována ve webovém obsahu:

async function EvaluateMeWithParamsAndAsyncReturn(s1, s2) {
    const response = await fetch("/asyncdata.txt");
    if (!response.ok) {
            throw new Error(`HTTP error: ${response.status}`);
    }
    var jsonData = await response.json();
    jsonData[s1] = s2;

    return jsonData;
}

Metodu EvaluateMeWithParamsAndAsyncReturn JavaScriptu je možné vyvolat z jazyka InvokeJavaScriptAsync C#:

Dictionary<string, string> asyncResult = await hybridWebView.InvokeJavaScriptAsync<Dictionary<string, string>>(
    "EvaluateMeWithParamsAndAsyncReturn", // JavaScript method name
    HybridSampleJSContext.Default.DictionaryStringString, // JSON serialization info for return type
    ["new_key", "new_value"], // Parameter values
    [HybridSampleJSContext.Default.String, HybridSampleJSContext.Default.String]); // JSON serialization info for each parameter

V tomto příkladu asyncResult je to Dictionary<string, string> , co obsahuje data JSON z webového požadavku.

Vyvolání metody vyžaduje zadání JsonTypeInfo objektů, které obsahují informace o serializaci pro typy použité v operaci. Tyto objekty se automaticky vytvářejí zahrnutím následující partial třídy do projektu:

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Dictionary<string, string>))]
[JsonSerializable(typeof(string))]
internal partial class HybridSampleJSContext : JsonSerializerContext
{
    // This type's attributes specify JSON serialization info to preserve type structure
    // for trimmed builds.  
}

Důležité

HybridSampleJsContext Třída musí být partial tak, aby generování kódu mohla poskytnout implementaci při kompilaci projektu. Pokud je typ vnořený do jiného typu, musí být partialtento typ také .