首先在nuget中安装CefSharp.Wpf组件用于解析html,是一个web浏览器内核,支持h5
我使用的CefSharp.Wpf版本是90.6.70
如果是.NET CORE或.NET5项目则用CefSharp.Wpf.NETCore
WPF目标框架:.NET5
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using CefSharp;
using CefSharp.Wpf;
namespace WpfApp1
{
/// <summary>
/// WindowWeb.xaml 的交互逻辑
/// </summary>
public partial class WindowWeb : Window
{
public WindowWeb()
{
InitializeComponent();
//WebBrowser webBrowser = new WebBrowser();
//webBrowser.Source = new Uri("http://www.baidu.com");
//grid01.Children.Add(webBrowser);
ChromiumWebBrowser webBrowser = new ChromiumWebBrowser();
//v.Title = "加载本地网页";
//webBrowser.Name = "加载本地网页";
// webBrowser.Address = "http://www.baidu.com";
//注入c#方法到前端页面
webBrowser.JavascriptObjectRepository.Register("csharpTest", new JavascriptCallCSharp(), true, BindingOptions.DefaultBinder);
webBrowser.JavascriptObjectRepository.ObjectBoundInJavascript += (sender, e) =>
{
var name = e.ObjectName;
System.Diagnostics.Debug.WriteLine($"对象 {e.ObjectName} 绑定成功.");
};
webBrowser.Address = AppDomain.CurrentDomain.BaseDirectory + "HTML/index.html";
grid01.Children.Add(webBrowser);
}
}
}
//功用:js调用C#后台方法
//创建时间:2021-7-9 10:20:39
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace WpfApp1
{
/// <summary>
/// js调用C#后台方法
/// </summary>
public class JavascriptCallCSharp
{
public void ShowMsg(string data)
{
MessageBox.Show($"当前时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "," + data);
}
}
}
准备静态页面
前端js调用C#方法,注意C#的后台方法在前端调用时,是骆驼命名的方法,首字母变为小写了,否则调用不会命中后台方法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>后台管理模板</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="format-detection" content="telephone=no">
<!--<link rel="stylesheet" href="plugins/layui/css/layui.css" media="all" />
<link rel="stylesheet" href="css/global.css" media="all">
<link rel="stylesheet" type="text/css" href="http://www.jq22.com/jquery/font-awesome.4.6.0.css">-->
</head>
<body>
<div>
WPF加载本地HTML,天下非一人一姓之天下,乃天下人之天下也
</div>
<div>
<a href="userList.html">用户页面</a>
</div>
<div style="margin:20px;">
<label>请输入传给后台的参数:</label>
<input type="text" id="txtName" />
<input type="button" value="调用C#方法" onclick="callBack01()"/>
</div>
<script type="text/javascript">
//CefSharp.BindObjectAsync("csharpTest");
(async function () {
await CefSharp.BindObjectAsync("csharpTest");
})();
function callBack01() {
try {
var txtName = document.getElementById("txtName").value;
//调用C#后台方法,方式一,无返回消息
csharpTest.showMsg(txtName);
} catch (e) {
alert(e);
}
}
</script>
</body>
</html>
如果C#方法有返回消息情况
using CefSharp;
using CefSharp.Wpf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WpfApp.JsCallMethod;
namespace WpfApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//加载浏览器内核
ChromiumWebBrowser webBrowser = new ChromiumWebBrowser();
webBrowser.FrameLoadEnd += WebBrowser_FrameLoadEnd;
//注入c#方法到前端页面
//注意前端调用的方法需要首字母小写,骆驼命名法,不然js调用C#方法会失败
webBrowser.JavascriptObjectRepository.Register("csharp_Common", new Common(), BindingOptions.DefaultBinder);
webBrowser.JavascriptObjectRepository.Register("csharp_Login", new Login(), BindingOptions.DefaultBinder);
webBrowser.JavascriptObjectRepository.Register("csharp_ProjectHandle", new ProjectHandle(), BindingOptions.DefaultBinder);
webBrowser.JavascriptObjectRepository.ObjectBoundInJavascript += (sender, e) =>
{
var name = e.ObjectName;
System.Diagnostics.Debug.WriteLine($"对象 {e.ObjectName} 绑定成功.");
};
//将本地html页面文件复制到C盘根目录
const string c_save_html = "C:\\tu_shi_fen_gong";
if (!System.IO.Directory.Exists(c_save_html))
{
System.IO.Directory.CreateDirectory(c_save_html);
}
string dir = AppDomain.CurrentDomain.BaseDirectory + "Html";
string[] files = System.IO.Directory.GetFiles(dir);
if (files != null && files.Length > 0)
{
foreach (var item in files)
{
string desPath = c_save_html + "\\" + System.IO.Path.GetFileName(item);
//if (System.IO.File.Exists(desPath))
//{
// continue;
//}
System.IO.File.Copy(item, desPath,true);
}
}
//System.IO.File.Copy();
// webBrowser.Address = "http://www.baidu.com";
//目录必须为英文,否则无法加载
//webBrowser.Address = AppDomain.CurrentDomain.BaseDirectory + "HTML/index.html";
webBrowser.Address = c_save_html + "\\index.html";
grid01.Children.Add(webBrowser);
}
private void WebBrowser_FrameLoadEnd(object sender, CefSharp.FrameLoadEndEventArgs e)
{
//隐藏滚动条
e.Browser.MainFrame.ExecuteJavaScriptAsync("document.body.style.overflow = 'hidden' ");
}
}
}
被注册到前端的C#方法
//功用:由前端页面js调用的C#方法集,WPF端,登录
//创建时间:2021-9-15 10:11:17
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing;
using WebMvcNetCore.TuShi.FenGong.IBusiness;
using Microsoft.Extensions.DependencyInjection;
namespace WpfApp.JsCallMethod
{
/// <summary>
/// js调用,WPF端,登录
/// </summary>
public class Login
{
/// <summary>
/// 获取当前登录验证码图片地址
/// </summary>
/// <returns></returns>
/// <remarks>
/// 创建时间:2021-9-14 17:47:17
/// </remarks>
public string GetVerificationCodeImgURL()
{
Random random2 = new Random();
int num = random2.Next(1000, 9999);
//生成的验证码
string code = num.ToString();
System.Runtime.Caching.MemoryCache.Default.Set("login.verification.code", code, DateTime.Now.AddSeconds(600));
//随机数生成验证码图片
int widthSpan = 4;
Bitmap image = new Bitmap((int)Math.Ceiling(code.Length * 28.0) + widthSpan, 40);
Graphics g = Graphics.FromImage(image);
try
{
//生成随机生成器
Random random = new Random();
//清空图片背景色
g.Clear(Color.White);
//画图片的干扰线
for (int i = 0; i < 25; i++)
{
int x1 = random.Next(image.Width);
int x2 = random.Next(image.Width);
int y1 = random.Next(image.Height);
int y2 = random.Next(image.Height);
g.DrawLine(new Pen(Color.DarkBlue), x1, y1, x2, y2);
}
Font font = new Font("Arial", 30, (FontStyle.Bold | FontStyle.Italic));
LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height),
Color.Blue, Color.DarkRed, 1.2f, true);
g.DrawString(code, font, brush, widthSpan, (image.Height - font.Height) / 2);
//画图片的前景干扰点
for (int i = 0; i < 100; i++)
{
int x = random.Next(image.Width);
int y = random.Next(image.Height);
image.SetPixel(x, y, Color.FromArgb(random.Next()));
}
string folder = AppDomain.CurrentDomain.BaseDirectory + "VerificationCodeImg\\";
if (!System.IO.Directory.Exists(folder))
{
System.IO.Directory.CreateDirectory(folder);
}
string filePath = folder + DateTime.Now.Ticks + ".jpg";
image.Save(filePath, ImageFormat.Jpeg);
g.Dispose();
image.Dispose();
return filePath;
}
catch (Exception)
{
}
return "";
}
/// <summary>
/// js调用,验证登录
/// </summary>
/// <param name="account"></param>
/// <param name="password"></param>
/// <param name="code"></param>
/// <returns></returns>
/// <remarks>
/// 创建时间:2021-9-16 14:42:48
/// </remarks>
public string DoLogin(string account, string password, string code)
{
IPersonBusiness personBusiness = InitInterface.provider.GetService<IPersonBusiness>();
//var result = await personBusiness.LoginCheck(account, password, code);
//return Newtonsoft.Json.JsonConvert.SerializeObject(result);
var task = personBusiness.LoginCheck(account, password, code);
return Newtonsoft.Json.JsonConvert.SerializeObject(task.Result);
}
}
}
前端代码调用C#方法,并取得返回消息:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>后台管理模板</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="format-detection" content="telephone=no">
</head>
<body>
<div>
WPF加载本地HTML,天下非一人一姓之天下,乃天下人之天下也
</div>
<div>
<a href="userList.html">用户页面</a>
</div>
<div style="margin:20px;">
<label>请输入传给后台的参数:</label>
<input type="text" id="txtName" />
<input type="button" value="调用C#方法" onclick="callBack01()"/>
</div>
<!--<div>
<button onclick="">调用后台方法</button>
</div>-->
<script type="text/javascript">
//CefSharp.BindObjectAsync("csharp_Login");
(async function () {
await CefSharp.BindObjectAsync("csharp_Login");
})();
function callBack01() {
try {
var txtName = document.getElementById("txtName").value;
//调用C#后台方法
csharp_Login.doLogin(txtName, '123456', '12KB')
.then(function (res) {
//c#方法返回消息
alert(res);
});
} catch (e) {
alert(e);
}
}
</script>
</body>
</html>