首页 > 其他分享 >WebView2UI - 在WPF之中使用WebView2的一些经验总结

WebView2UI - 在WPF之中使用WebView2的一些经验总结

时间:2024-06-22 09:42:29浏览次数:22  
标签:CoreWebView2 await WebView2 WebView2UI window html user WPF webView

项目地址:https://gitee.com/skyw18/WebView2UI

项目地址:https://github.com/skyw18/WebView2UI

webview简介与生命周期:WPF 应用中的 WebView2 入门 - Microsoft Edge Developer documentation | Microsoft Learn

具体代码可以参考微软官方示例文档 WPF 示例应用 - Microsoft Edge Developer documentation | Microsoft Learn

使用方法:

使用nuget添加Microsoft.Web.WebView2,将Resource目录下的app子目录复制到生成的可执行文件同一目录,xaml之中插入 xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"

如果需要使用webview2 prerelease版,需要在NuGet管理界面进入项目网页,然后在下面的Package Manager之中复制命令行到程序包管理控制台,在上面的下拉菜单之中选择要安装的项目,然后运行命令即可。

初始化Webview2和几种加载html的方式

public MainWindow()
{
    InitializeComponent();
    InitializeAsync();
}

async void InitializeAsync()
{
    //加载之前需等待webview2 initialized完成。
    await webView.EnsureCoreWebView2Async(null);

    //webview2加载资源的几种方式,也可以在XAML里设定source,可以使用1,2两种方法
    //1. 直接通过URL加载网络页面
    //webView.Source = new Uri("https://localhost:44380");

    //2. 通过路径加载本地页面
    webView.Source = new Uri("file:///" + System.Environment.CurrentDirectory + "\\app\\index.html");

    //3. 将本地路径设为虚拟域名,通过虚拟域名加载本地页面
    //请注意,SetVirtualHostNameToFolderMapping这个方法需等待webview初始化完成,否则会因webview为空而崩溃,
    //所以不能放在MainWindow之中同步执行,会卡死,也不能放在wvMain.CoreWebView2InitializationCompleted和NavigationCompleted之中执行,
    //因为这两个方法都是加载完页面之后才会触发,如果xaml之中source为空,则永不会被执行,所以需在MainWindow异步执行并通过EnsureCoreWebView2Async方法等待:
    //webView.CoreWebView2.SetVirtualHostNameToFolderMapping("appassets.example", "app", CoreWebView2HostResourceAccessKind.Allow);
    //webView.Source = new Uri("https://appassets.example/hello.html");

    //4. 直接加载html字符串  加载的字符串大小不能大于2m 
    //html之中资源的链接必须通过虚拟域名,资源放在跟执行程序同一个目录下也无法直接调用
    //string htmlContent = @"<img src='http://appassets.example/bg0.jpg'>";
    //string htmlContent = @"<h1>hello, world!</h1>";
    //webView.NavigateToString(htmlContent);         
}

开发混合应用时用到的一些功能

async void InitializeAsync()
{
    //..... 初始化代码,省略,参考上面
    
    //webview2控件设定透明度        
    //webView.DefaultBackgroundColor = System.Drawing.Color.Transparent;

    //下面这行语句可以禁用f5等快捷键 以阻止用户误触f5刷新页面
    webView.CoreWebView2.Settings.AreBrowserAcceleratorKeysEnabled = false;
    //禁止缩放界面比例
    webView.CoreWebView2.Settings.IsZoomControlEnabled = false;

    webView.NavigationCompleted += webView_NavigationCompleted;
    //webView.CoreWebView2InitializationCompleted += webView_InitializationCompleted;
    //webView.NavigationStarting += EnsureHttps;
    //webView.NavigationCompleted += CancelRightButton;
    webView.WebMessageReceived += WebView_WebMessageReceived; 
}

async void webView_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs args)
{
    //一些使用js实现的功能
    //禁止鼠标右键菜单
    await webView.CoreWebView2.ExecuteScriptAsync("window.addEventListener('contextmenu', window => {window.preventDefault();});");
    //禁止鼠标左键拖动选择
    await webView.CoreWebView2.ExecuteScriptAsync("window.addEventListener('selectstart', window => {window.preventDefault();});");
    //禁止拖动文件到窗口
    await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(
           "window.addEventListener('dragover',function(e){e.preventDefault();},false);" +
           "window.addEventListener('drop',function(e){" +
              "e.preventDefault();" +
              "console.log(e.dataTransfer);" +
              "console.log(e.dataTransfer.files[0])" +
           "}, false);");
    //await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.chrome.webview.postMessage(window.document.URL);");
    //await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.chrome.webview.addEventListener(\'message\', event => alert(event.data));");
    //await webView.CoreWebView2.ExecuteScriptAsync($"alert('alertt');document.getElementById('hello').innerHTML='hello;");
}

C#在html之中插入脚本

await wView.CoreWebView2.ExecuteScriptAsync("some_func();");  //执行JS
var result = await webView.CoreWebView2.ExecuteScriptWithResultAsync("get_json();"); //执行带返回值的JS
string scriptResult = await _webViewFrames[iframeNumber].ExecuteScriptAsync(dialog.Input.Text);  //插入 iFrame

若html内容如下:

var user_id = 120; //数字
var user_name = "hello"; //字符串
var user_info = {name: "hello",age: 12}; //json串
function get_user_name() {return user_name;}
function get_user_id() {return user_id;}
function get_user_info() {return user_info;}

使用SimpleJSON对返回数据进行处理:

var result_user_id = await webView.CoreWebView2.ExecuteScriptWithResultAsync("user_id");
//等效于 var result_user_id = await webView.CoreWebView2.ExecuteScriptWithResultAsync("get_user_id()");
long user_id = JSON.Parse(result_user_id.ResultAsJson).AsLong;//处理数值
//如果数值过大则会自动加双引号此时需long.TryParse(result.ResultAsJson.Replace("\"", ""), out t);

//处理字符串
var result_user_name = await webView.CoreWebView2.ExecuteScriptWithResultAsync("get_user_name();");
string user_name = JSON.Parse(result_user_name.ResultAsJson).Value;

//处理json串
var result_user_info = await webView.CoreWebView2.ExecuteScriptWithResultAsync("get_user_info();");
var json = JSON.Parse(result_user_info.ResultAsJson);//通过json["user_name"].Value 获取值 

C#发送数据,html接收

C#发送:

webView.CoreWebView2.PostWebMessageAsJson(reply);
webView.CoreWebView2.PostWebMessageAsString(dialog.Input.Text);

html接收数据:

window.chrome.webview.addEventListener('message', arg => {
   if ("WindowBounds" in arg.data) {
       document.getElementById("window-bounds").value = arg.data.WindowBounds;
   }
   if ("SetColor" in arg.data) {
       document.getElementById("colorable").style.color = arg.data.SetColor;
   }
});  

html发送数据,C#接收

html发送:

window.chrome.webview.postMessage("GetWindowBounds");

C#接收:

wvMain.WebMessageReceived += wvMain_WebMessageReceived;

C#增加和删除js脚本

Enter the JavaScript code to run as the initialization script that runs before any script in the HTML document.

在任何js脚本之前运行

string scriptId = await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(dialog.Input.Text);
webView.CoreWebView2.RemoveScriptToExecuteOnDocumentCreated(scriptId);

标签:CoreWebView2,await,WebView2,WebView2UI,window,html,user,WPF,webView
From: https://www.cnblogs.com/skyw18/p/18261878

相关文章

  • 【C#】WPF 类库项目 无法创建 “资源字典” 文件
    解决办法打开项目工程文件(project.csproj)在标签添加下面红色的三句话<Deterministic>true</Deterministic><ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids><WarningLevel>......
  • WPF程序本地化要点梳理
    WPF程序支持国际化的编码、语言、布局等,能够设置根据目标市场实现文字显示的本地化。程序本地化要点:1.给项目的.csproj文件的无条件的元素添加类似zh-CN的标记,编译时会把可国际化的元素单独生成一个<项目名称>.resources.dll文件,供翻译使用。注:本方法通过dll单独存储可......
  • 基于C#的WPF+halcon开发,视觉和运动控制软件框架源码
    基于C#的WPF+halcon开发,视觉和运动控制软件框架源码带ui设计器和轴卡运控,上手可用,WPFMVVM开发模式,1:1参考easyvision开发,集成几十个软件算子,插件框架可以自定义变量,写c#脚本,自定义流程,包含了halcon脚本和封装的算子,可自定义ui,通过插件形式开发很方便拓展自己的功能。可学......
  • WPF/C#:数据绑定到方法
    在WPFSamples中有一个关于数据绑定到方法的Demo,该Demo结构如下:运行效果如下所示:来看看是如何实现的。先来看下MainWindow.xaml中的内容:<Window.Resources><ObjectDataProviderObjectType="{x:Typelocal:TemperatureScale}"MethodName="Con......
  • WPF控件库 https://wpfui.lepo.co/
    wpfui:一个开源免费具有现代化设计趋势的WPF控件库 https://wpfui.lepo.co/合集-C#(46) 1.使用C#将几个Excel文件合并去重分类2023-11-152.C#使用SqlSugar操作MySQL数据库实现简单的增删改查2023-11-163.C#中的类和继承2023-11-174.C#中的virtual和override关键字2023-......
  • WPF绘制3D小demo
    试过了WPF原生3D和HelixToolkit.Wpf,感觉还是SharpDX的效果比较好,所以使用了HelixToolkit.Wpf.SharpDX初学,仅供参考,没搞懂怎么双面渲染,所以每个面用了2个三角形分别显示正面和反面 <Grid><hx:Viewport3DXEnableSwapChainRendering="True"FXAALevel="Low"Backg......
  • WPF支持任意快捷键+鼠标组合的绑定类
    publicinterfaceIInputSignal{boolIsMatch(InputEventArgsargs);}publicclassKeyDownSignal:KeySignal{publicKeyDownSignal(Keykey):base(key){}publicoverrideboolIsMatch(InputEve......
  • 演示:WPF开发的Diagram自动化流程图应用
    一、目的:演示Diaram应用功能二、预览三、功能列表功能模块通用测试流程图仪器仪表机器人网络通信测试PLC测试轮毂生产线流程测试 图像处理目标检测绘图思维导图图表流程图功能模板管理工程管理模块许可管理工具栏开始停止删除清......
  • DevExpress WPF中文教程:Grid - 如何将更改发布到数据库(设计时)?
    DevExpressWPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。无论是Office办公软件的衍伸产品,还是以数据为中心......
  • WPF/C#:在DataGrid中显示选择框
    前言在使用WPF的过程中可能会经常遇到在DataGrid的最前或者最后添加一列选择框的需求,今天跟大家分享一下,在自己的项目中是如何实现的。整体实现效果如下:如果对此感兴趣,可以接下来看具体实现部分。实践假设数据库中的模型如下:publicclassPerson{publicintId......