原文发表在我的个人搭建的博客网站上:博客链接,下面是直接复制过来的

Winform/WPF集成vue开发

前言

有时候因为各种原因,可能在开发winform或wpf项目的时候需要嵌入web项目,而目前vue在web开发中还是非常流行的,今天有空琢磨了一下怎么在winform中集成vue进行开发,当然,winform能实现,wpf也是一样的。

目前希望达到的效果是,能够在winform中显示web界面,并且能够与vue中的各个组件进行交互,也就是调用vue中的函数,及vue函数调用C#中的方法。

项目创建

首先,先用vue-cli建个demo项目,这里就不进行详细介绍了,网上教程很多,由于我之前写了一个vue的demo项目,因此这里直接拿过来用,项目结构如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c4CX3WJS-1641622687742)(WinformWPF%E9%9B%86%E6%88%90vue%E5%BC%80%E5%8F%91.assets/image-20220108133036054.png)]

Login.vue组件是在打开之后就显示的登录界面,这个不重要,用vue新建项目的初始界面也行。

然后在VS里面新建一个WPF或者Winform项目,我这里用的是winform,wpf同理,创建好后用nuget安装一下CefSharp.WinForms,我用的版本是最新版96.0.180.0,接着在窗体界面上加几个button和一个panel,panel用来装cefsharp的控件类,最后弄完了,窗体界面差不多是这个样子的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mdOtozue-1641622687743)(WinformWPF%E9%9B%86%E6%88%90vue%E5%BC%80%E5%8F%91.assets/image-20220108133352742.png)]

把Vue集成进winform

使用npm run build命令生成打包后的dist文件夹,直接把文件夹放在winform构建好的debug文件夹下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qjOD1FZd-1641622687744)(WinformWPF%E9%9B%86%E6%88%90vue%E5%BC%80%E5%8F%91.assets/image-20220108133535260.png)]

注意,index.html文件内对css和js的引用路径必须是相对路径./,不能是/,不对的话记得替换一下,然后使用如下代码加载html:

 private void button1_Click(object sender, EventArgs e)
 {
     string path = AppDomain.CurrentDomain.BaseDirectory + @"dist/index.html";
     browser = new ChromiumWebBrowser(path);
     browser.JavascriptObjectRepository.Settings.LegacyBindingEnabled = true;

    webPanel.Controls.Add(browser);
}

这个事件对应了加载浏览器按钮的点击事件,全部搞好后运行winform程序,点击第一个按钮,如果出现下面的界面说明成功了:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1QkrbIwG-1641622687745)(WinformWPF%E9%9B%86%E6%88%90vue%E5%BC%80%E5%8F%91.assets/image-20220108133859426.png)]

Winform调用Vue组件

winform在正常情况下是没有办法直接调到vue组件内部的事件的,会提示undefine,因此我们选择迂回战术,通过document.addEventListener的方式来监听自定义事件,然后再通过vue的全局事件总线来发布消息,传给需要的组件。

首先,我们先在main.js文件内给vue加个全局的事件总线:

let bus = new Vue();
Vue.prototype.$EventBus = bus;

接着,还是在main.js文件,使用document来添加事件监听:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4v5hgfdS-1641622687746)(WinformWPF%E9%9B%86%E6%88%90vue%E5%BC%80%E5%8F%91.assets/image-20220108134115465.png)]

在对应的Login.vue组件内,我们通过下面代码来添加组件对消息的订阅和取消订阅:

mounted() {
    this.$EventBus.$on("test", (msg) => {
      alert("Login组件接收到了消息:" + msg);
      console.log("接收到了消息" + msg);
    });
},
unmounted() {
  this.$EventBus.$off();
},

vue这边就添加完成了,重新npm run build之后再复制到winform的debug文件夹下,还是一样的套路。

接着我们就可以在winform中调用事件触发了:

  private void button2_Click(object sender, EventArgs e)
  {
      browser.GetBrowser().MainFrame.ExecuteJavaScriptAsync("document.dispatchEvent(new CustomEvent('test',{detail:{param1:'我是参数1',param2:'我是参数2'}}))");
  }

来看看运行的结果,在启动项目后用browser.ShowDevTools()这段代码把浏览器的开发者工具打开,然后我们调用上面的button2_click事件:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b76bgp8t-1641622687746)(WinformWPF%E9%9B%86%E6%88%90vue%E5%BC%80%E5%8F%91.assets/image-20220108134810930.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZUPWysZr-1641622687747)(WinformWPF%E9%9B%86%E6%88%90vue%E5%BC%80%E5%8F%91.assets/image-20220108134829667.png)]

大功告成,winform调vue就这样结束了。

Vue调用winform

Vue调用winform比较简单,首先在winform代码中添加一个要注入浏览器的对象:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yQJucNJz-1641622687747)(WinformWPF%E9%9B%86%E6%88%90vue%E5%BC%80%E5%8F%91.assets/image-20220108140227775.png)]

然后在vue的组件里面随便写个button,在这个button对应的click事件里面加上这两行代码:

CefSharp.BindObjectAsync("csharpinstance");
csharpinstance.func("para");

就这样写就完成了,记得重新build一下复制到debug文件夹下,再次运行,看看能不能成功调用并且把值传过去:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J3yW0ZPa-1641622687748)(WinformWPF%E9%9B%86%E6%88%90vue%E5%BC%80%E5%8F%91.assets/image-20220108140033924.png)]

大功告成!

后话

虽然winform和vue相互调用就这样写完了,看似比较简单,但是其实还有很多困难点存在,比如winform要实现无窗体标题栏下的拖拽、主题替换、半透明,或者WPF里面要实现一些放大缩小的动画效果,也不好保持两边动画的统一,所有感觉没有十分必要的情况下,最好还是统一用winform/wpf,或者直接用浏览器端,不套个web进去。

Logo

前往低代码交流专区

更多推荐