WinUI 3 (Windows 应用 SDK) 示例应用

  • 示例名称: WebView2_WinUI3_Sample
  • 存储库目录: WebView2_WinUI3_Sample
  • 解决方案文件: WebView2_WinUI3_Sample.sln

此示例演示如何在 WinUI 3 (Windows 应用 SDK) 打包应用程序中使用 WebView2 控件。

示例应用

此示例还允许你将应用与固定版本的 WebView2 运行时一起交付,而不是使用在用户计算机上安装并运行的 WebView2 运行时版本。

NuGet 包和工作负载组件

在生成之前,我们将执行以下操作:

  • 更新项目和 (包) 项目的 Microsoft.Windows.SDK.BuildTools NuGet 包。
  • 更新项目和 (包) 项目的 Microsoft.WindowsAppSDK NuGet 包。
  • 安装“Windows 应用开发”工作负载的“Windows 10 SDK”组件(如果尚未安装)。

目录

目录 目录
WebView2_WinUI3_Sample 项目代码
WebView2_WinUI3_Sample (包) 打包和分发项目
WebView2_WinUI3_Sample (包) \FixedRuntime (可选) 固定 WebView2 运行时
WebView2_WinUI3_Sample (包) \FixedRuntime\130.0.2849.39 (可选) 固定 WebView2 运行时示例

步骤 1:安装最新的 Visual Studio 2022

确保已安装 Visual Studio 2022 并处于最新状态。

若要安装最新的 Visual Studio 2022,请执行以下操作:

  1. 转到 Visual Studio:面向软件开发人员和 Teams 的 IDE 和代码编辑器,然后在 Visual Studio 2022 部分中,单击“下载”按钮,然后选择“社区 2022 或其他版本”。

  2. 在 Microsoft Edge 右上角的 “下载” 弹出窗口中, VisualStudioSetup.exe 列出了 。 单击“ 打开文件”。

    Visual Studio 安装程序打开。

  3. 按照提示操作,并接受默认值。

步骤 2:克隆或下载 WebView2 示例存储库

  1. 如果尚未执行此操作,请将 WebView2Samples 存储库克隆或下载到本地驱动器。 在单独的窗口或选项卡中,请参阅为 WebView2设置开发环境中的下载 WebView2 示例存储库。 按照该部分中的步骤操作,然后返回到此页面,然后继续以下操作。

步骤 3:在 Visual Studio 中打开解决方案

不需要这些有关存储库和分支的初始步骤,但它们是一个很好的做法,以避免更改 WebView2Samples 存储库克隆副本的“main”分支中的代码。 这使你可以更改项目 (的文件,以便生成和运行示例) ,同时将“main”分支中的代码与存储库相同。

可以在任何 Git 操作工具中执行这些步骤,例如:

  • GitHub Desktop。
  • Visual Studio 右下角的“解决方案资源管理器”选项卡旁边的“Git 更改”选项卡。
  • git bash 命令提示符。

若要在工作分支中打开示例的解决方案文件,请执行以下操作:

  1. 在 GitHub Desktop 中,在左上角的 “当前存储库 ”列表中,选择 “WebView2Samples ”存储库。

  2. 单击窗口中上方的“ 提取原点 ”。

  3. “当前分支 ”菜单中,创建一个工作分支,例如 user/myGithubUsername/winui3-sample 并切换到它。

    你现在安全地位于工作分支而不是“main”分支中,并且可以自由地开始更改示例的文件。

  4. 在本地驱动器上,在 Visual Studio 中打开 .sln 文件。

    文件的示例位置 .sln :如果克隆了存储库,则存储库目录名称为 /WebView2Samples/

    <your-repos-directory>/WebView2Samples/SampleApps/WebView2_WinUI3_Sample/WebView2_WinUI3_Sample.sln

    如果下载了存储库,则存储库目录名称为 /WebView2Samples-main/,表示“main”分支:

    <your-repos-directory>/WebView2Samples-main/SampleApps/WebView2_WinUI3_Sample/WebView2_WinUI3_Sample.sln

步骤 4:更新 NuGet 包

  1. 在“解决方案资源管理器”中,右键单击“WebView2_WinUI3_Sample”项目,然后选择“管理 NuGet 包”。

    在 Visual Studio 中, NuGet 包管理器 打开:

    NuGet 包管理器显示已安装的、已更新的包

    选中“ 已安装 ”选项卡,其中列出了 NuGet 包:

    • Microsoft.Windows.SDK.BuildTools
    • Microsoft.WindowsAppSDK
    • Microsoft.Web.WebView2
  2. 选择“汇报”选项卡。

  3. 在左上角,选中“ 选择所有包 ”复选框。

  4. 在该复选框的右侧,单击“ 更新 ”按钮。

    此时会打开 “预览更改 ”对话框。

  5. 单击“ 应用 ”按钮。

    此时将打开“ 接受许可证 ”对话框。

  6. 单击“ 我接受 ”按钮。

    NuGet 包已更新,并删除“汇报”选项卡旁边的编号。

  7. 单击“ 视图 ”菜单,然后单击“ 输出 ”菜单项。

    在“ 输出 ”选项卡的“ 显示输出” 下拉列表中,选择了 “包管理器 ”。 输出包括以下行:

    Installing NuGet package Microsoft.Windows.SDK.BuildTools
    Installing NuGet package Microsoft.WindowsAppSDK
    
    Successfully uninstalled 'Microsoft.Windows.SDK.BuildTools
    Successfully uninstalled 'Microsoft.WindowsAppSDK
    
    Successfully installed 'Microsoft.Web.WebView2
    Successfully installed 'Microsoft.Windows.SDK.BuildTools
    Successfully installed 'Microsoft.WindowsAppSDK
    

    更新 (包) 项目中的 NuGet 包

  8. 在“解决方案资源管理器”中,右键单击“WebView2_WinUI3_Sample (包) ”项目,然后选择“管理 NuGet 包”。

  9. 选择“汇报”选项卡。

  10. 在左上角,选中“ 选择所有包 ”复选框。

  11. 在该复选框的右侧,单击“ 更新 ”按钮。

    此时会打开 “预览更改 ”对话框。

  12. 单击“ 应用 ”按钮。

    此时将打开“ 接受许可证 ”对话框。

  13. 单击“ 我接受 ”按钮。

    NuGet 包已更新,并删除“汇报”选项卡旁边的编号。

  14. 单击“ 视图 ”菜单,然后单击“ 输出 ”菜单项。

    在“ 输出 ”选项卡的“ 显示输出” 下拉列表中,选择了 “包管理器 ”。 输出包含如上所示的行。

  15. 关闭 “NuGet 包管理器 ”窗口。

步骤 5:安装 Windows 10 SDK 或其他工作负载组件

根据已安装的内容,可能需要安装 Visual Studio 工作负载或工作负载的组件,如下所示,以生成示例。

若要安装 Windows 应用程序开发工作负载的 Windows 10 SDK 组件,请执行以下操作:

  1. 在 Visual Studio 中,单击“ 工具 ”菜单,然后单击“ 获取工具和功能 ”菜单项。

    此时会打开Visual Studio 安装程序窗口。

  2. 选择 Windows 应用程序开发卡,以便显示复选标记。

  3. 在右侧的“安装详细信息”树中,选中“Windows 10 SDK 10.0.19041.0”组件的复选框。

  4. 单击“ 修改” 按钮。

    此时将打开 “用户帐户控制 ”对话框。

  5. 单击“ ”按钮。

    “开始之前”对话框 (Visual Studio 安装程序) 打开,提示在 Visual Studio 中保存工作。

  6. 关闭main Visual Studio 窗口,根据需要保存。

  7. “开始之前 ”对话框中,单击“ 重试” 按钮。

    几分钟后,将下载并安装Windows 10 SDK 10.0.19041.0 工作负载组件。 Visual Studio 安装程序说“所有安装都是最新的。

步骤 6:生成并运行应用

  1. 在 Visual Studio 2022 中打开解决方案。 例如,在 Visual Studio 安装程序Visual Studio 2022 部分中,单击“启动”按钮。

    Visual Studio 启动器随即打开,其中包含 “最近打开 ”和 “入门”部分。

  2. “打开最近打开 ”部分中,选择“ WebView2_WinUI3_Sample.sln”。

    解决方案将在 Visual Studio 2022 中打开。

  3. F5

    在 解决方案资源管理器 中, (包) 项目为粗体,指示它是默认项目。 应用生成,然后打开 “WebView2_WinUI3_Sample (包) 应用”窗口:

    示例应用

    消息“导航完成”显示在底部。

  4. 在“地址栏” () 文本框中,输入 https://bing.com (完整的 HTTPS URL) ,然后按 Enter (等效于单击“ 转到 ”按钮) 。

    WebView2 控件导航到必应,然后在底部显示“导航完成”。

    在 Visual Studio 中, “输出 ”窗口显示如下消息:

    AddressBar_KeyDown [Enter]: https://bing.com
    TryNavigate
    TryCreateUri
    Navigation complete
    

步骤 7:提交工作分支中的更改

在 GitHub Desktop 等 Git 工具中,此时可以提交更改,并选择性地将其推送到 GitHub 分支的分支。 修改、试验和自定义示例时,这些类型的操作是相关的。 这也使工作分支保持干净,并使存储库的克隆保持井然有序,以便可以切换到其他示例。

若要提交并推送对工作分支中示例所做的更改,请执行以下操作:

  1. 在 Visual Studio 中,选择“ 全部文件>保存 ” (Ctrl+Shift+S) 。

  2. 在 GitHub Desktop 中,输入简短提交消息,例如“已更新、生成、运行的示例”,然后单击“提交”按钮。

  3. 选择 “存储库>推送”。 工作分支将从本地驱动器复制到 GitHub 上 WebView2Samples 存储库的分支分支。

    在 GitHub 上查看工作分支

  4. 在 Microsoft Edge 中,转到存储库的分支,例如 https://github.com/myGithubUsername/WebView2Samples/

  5. 单击 “[#] 分支 ”链接,然后选择新的工作分支,例如 user/myGithubUsername/winui3-sample

步骤 8:检查代码

  1. 关闭 WebView2_WinUI3_Sample (包) 应用。

  2. 在 解决方案资源管理器 的 WebView2_WinUI3_Sample 项目中,双击每个.xaml文件及其.cs文件:

    • App.xaml - 无 WebView2 代码。
      • App.cs - 使用固定版本的 WebView2 运行时的代码。
    • MainWindow.xaml - WebView2 元素。
      • MainWindow.cs - WebView2 代码。

这些文件的精简版本如下所示。

App.xaml

此文件中没有特定于 WebView2 的代码。

精简列表
<Application
    x:Class="WebView2_WinUI3_Sample.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WebView2_WinUI3_Sample">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

App.cs

此文件中特定于 WebView2 的代码将被注释掉。若要使用固定版本的运行时,可以取消注释这些行;请参阅下面的 使用固定版本的 WebView2 运行时

精简列表
namespace WebView2_WinUI3_Sample
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    public partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton application object.  Equivalent to main() or WinMain().
        /// </summary>
        public App()
        {
            this.InitializeComponent();

            // If you're shipping a fixed-version WebView2 Runtime with your app, un-comment the
            // following lines of code, and change the version number to the version number of the
            // WebView2 Runtime that you're packaging and shipping to users:

            // StorageFolder localFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
            // String fixedPath = Path.Combine(localFolder.Path, "FixedRuntime\\130.0.2849.39");
            // Debug.WriteLine($"Launch path [{localFolder.Path}]");
            // Debug.WriteLine($"FixedRuntime path [{fixedPath}]");
            // Environment.SetEnvironmentVariable("WEBVIEW2_BROWSER_EXECUTABLE_FOLDER", fixedPath);
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.
        /// </summary>
        /// <param name="args">Details about the launch request and process.</param>
        protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
        {
            m_window = new MainWindow();
            m_window.Activate();
        }

        private Window m_window;
    }
}

MainWindow.xaml

main窗口具有以下 XAML 元素作为控件:

  • <TextBox> - 地址栏。
  • <Button> - “ 转到 ”按钮。
  • <WebView2> - WebView2 控件。
  • <TextBlock> - 状态栏。
精简列表
<Window
    xmlns:local="using:WebView2_WinUI3_Sample">
    <Grid>
        <Grid.RowDefinitions>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0" Background="LightGray">
            <TextBox Grid.Column="0"  x:Name="AddressBar" KeyDown="AddressBar_KeyDown" VerticalAlignment="Center" Margin="10,0,0,0"/>
            <Button Grid.Column="1" x:Name="Go" Content="Go" Click="Go_OnClick" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        </Grid>

        <WebView2 x:Name="WebView2" Grid.Row="1"/>

        <Rectangle Grid.Row="2" Fill="LightGray"/>
        <TextBlock x:Name="StatusBar" Text="WebView2" VerticalAlignment="Center" Grid.Row="2" Margin="10,0,10,0"/>
    </Grid>
</Window>

MainWindow.cs

MainWindow 类具有以下方法:

这些方法的摘录或精简版本如下。

MainWindow 类
using Microsoft.Web.WebView2.Core;

namespace WebView2_WinUI3_Sample
{
    /// <summary>
    /// An empty window that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainWindow : Window
    {
无。
public MainWindow()
{
    this.InitializeComponent();

    Closed += (obj, eventArgs) =>
    {
        if (WebView2 != null)
        {
            // Ensure that WebView2 resources are released when
            // the MainWindow is closed. 
            // WebView2 lifecycle in WinUI3 and the Close() method:
            // https://github.com/microsoft/microsoft-ui-xaml/issues/4752#issuecomment-819687363
            WebView2.Close();
        }
    };

    AddressBar.Text = "https://developer.microsoft.com/en-us/microsoft-edge/webview2/";

    WebView2.NavigationCompleted += WebView2_NavigationCompleted;
    WebView2.CoreWebView2Initialized += WebView2_CoreWebView2Initialized;

    WebView2.Source = new Uri(AddressBar.Text);
    StatusUpdate("Ready");
    SetTitle();
}
StatusUpdate
private void StatusUpdate(string message)
{
    StatusBar.Text = message;
    Debug.WriteLine(message);
}
WebView2_CoreWebView2Initialized
private void WebView2_CoreWebView2Initialized(WebView2 sender, CoreWebView2InitializedEventArgs args)
{
    if (args.Exception != null)
    {
        StatusUpdate($"Error initializing WebView2: {args.Exception.Message}");
    }
    else
    {
        SetTitle(sender);
    }
}
WebView2_NavigationCompleted
private void WebView2_NavigationCompleted(WebView2 sender, CoreWebView2NavigationCompletedEventArgs args)
{
    StatusUpdate("Navigation complete");

    // Update the address bar with the full URL that was navigated to.
    AddressBar.Text = sender.Source.ToString();
}
TryCreateUri
private bool TryCreateUri(String potentialUri, out Uri result)
{
    StatusUpdate("TryCreateUri");

    Uri uri;
    if ((Uri.TryCreate(potentialUri, UriKind.Absolute, out uri) || Uri.TryCreate("http://" + potentialUri, UriKind.Absolute, out uri)) &&
        (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
    {
        result = uri;
        return true;
    }
    else
    {
        StatusUpdate("Unable to configure URI");
        result = null;
        return false;
    }
}
TryNavigate
private void TryNavigate()
{
    StatusUpdate("TryNavigate");

    Uri destinationUri;
    if (TryCreateUri(AddressBar.Text, out destinationUri))
    {
        WebView2.Source = destinationUri;
    }
    else
    {
        StatusUpdate("URI couldn't be figured out use it as a bing search term");

        String bingString = $"https://www.bing.com/search?q={Uri.EscapeDataString(AddressBar.Text)}";
        if (TryCreateUri(bingString, out destinationUri))
        {
            AddressBar.Text = destinationUri.AbsoluteUri;
            WebView2.Source = destinationUri;
        }
        else
        {
            StatusUpdate("URI couldn't be configured as bing search term, giving up");
        }
    }
}
Go_OnClick
private void Go_OnClick(object sender, RoutedEventArgs e)
{
    StatusUpdate("Go_OnClick: " + AddressBar.Text);

    TryNavigate();
}
AddressBar_KeyDown
private void AddressBar_KeyDown(object sender, KeyRoutedEventArgs e)
{
    if (e.Key == Windows.System.VirtualKey.Enter)
    {
        StatusUpdate("AddressBar_KeyDown [Enter]: " + AddressBar.Text);

        e.Handled = true;
        TryNavigate();
    }
}
SetTitle
private void SetTitle(WebView2 webView2 = null)
{
    var packageDisplayName = Windows.ApplicationModel.Package.Current.DisplayName;
    var webView2Version = (webView2 != null) ? " - " + GetWebView2Version(webView2) : string.Empty;
    Title = $"{packageDisplayName}{webView2Version}";
}
GetWebView2Version
private string GetWebView2Version(WebView2 webView2)
{
    var runtimeVersion = webView2.CoreWebView2.Environment.BrowserVersionString;

    CoreWebView2EnvironmentOptions options = new CoreWebView2EnvironmentOptions();
    var targetVersionMajorAndRest = options.TargetCompatibleBrowserVersion;
    var versionList = targetVersionMajorAndRest.Split('.');
    if (versionList.Length != 4)
    {
        return "Invalid SDK build version";
    }
    var sdkVersion = versionList[2] + "." + versionList[3];

    return $"{runtimeVersion}; {sdkVersion}";
}

使用固定版本的 WebView2 运行时

如果要将固定版本的 WebView2 运行时与应用程序一起交付,则需要将其包含在项目中。 请参阅 分发应用和 WebView2 运行时

以下步骤显示了运行时版本号 130.0.2849.39;你将将此编号更改为要打包和寄送的任何版本。

若要使用固定版本的运行时::

  1. 在包项目中包括固定的 WebView2 运行时:

    \WebView2_WinUI3_Sample\WebView2_WinUI3_Sample (Package)\FixedRuntime\130.0.2849.39\
    

    在上面,请使用要交付的版本,而不是 130.0.2849.39

  2. 更新正在使用的版本的包项目 wapproj 文件, (使用版本而不是 130.0.2849.39) :

    < Content Include="FixedRuntime\130.0.2849.39\\**\*.*" >
    
  3. App.xaml.cs中,取消注释下方的五行代码注释,以启用运行时替代:

    public App()
    {
       this.InitializeComponent();
    
       // If you're shipping a fixed-version WebView2 Runtime with your app, un-comment the
       // following lines of code, and change the version number to the version number of the
       // WebView2 Runtime that you're packaging and shipping to users:
    
       // StorageFolder localFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
       // String fixedPath = Path.Combine(localFolder.Path, "FixedRuntime\\130.0.2849.39");
       // Debug.WriteLine($"Launch path [{localFolder.Path}]");
       // Debug.WriteLine($"FixedRuntime path [{fixedPath}]");
       // Environment.SetEnvironmentVariable("WEBVIEW2_BROWSER_EXECUTABLE_FOLDER", fixedPath);
    }
    
  4. 在上面的代码中,将版本号从 130.0.2849.39 更改为要交付的版本。

另请参阅