CodeFirst写界面——自己写客户端UI库

何谓CBS程序

CBS程序就是Client+Browser+Service的程序

纯CS程序写界面,有各种难处,那么我就在Client端引入Browser,让Browser渲染基于HTML的UI界面

何谓WUI

就算用用HTML渲染UI界面,那么开发人员还是要掌握HTML+CSS+JS的知识,这些知识还是比较复杂的

WUI库就是把HTML+CSS+JS封装成起来,组成一个界面元素库,(类似于Extjs和easyui)

意图是让开发人员就只要掌握C#代码,就能写出漂亮的UI界面

第一步:WUI库中的主窗口

一个WinForm程序必然有一个主窗口 我们把这个主窗口封装到WUI库中

这个主窗口里面有一个WebBrowser,(这对于最终的用户来说是不可见的,最终使用者不会操作这个WebBrowser)

第二步:基础的UI资源

我们在WUI库中添加了一些基础的UI资源,注意这些资源都会被复制到输出目录中,以后会考虑把这些内容做到Resource 中

Index.html代码中有两点需要说明: 第一点:<meta http-equiv="X-UA-Compatible" content="IE=9" /> 这是让我们使用的WebBrowser,以IE9的模式来渲染界面,这一行代码很重要,没有这一行代码,就算你装了IE11,那么WebBrowser可能仍旧不会表现成你想象的那样; 第二点:window.external.WUIPageLoaded(); 这行代码会触发WUI库的内部事件,告诉最终用户基础的界面渲染已经完成了,用户可以在这个事件触发后,添加自己的界面元素。 这里涉及到JS和C#通讯,待会儿再说。

第三步:CodeFirst创建UI

我们的WUI.Demo程序是一个WinForm程序集,但是我把IDE默认生成的那个窗口(Form1)删掉了,而且修改了一下Program.cs程序

在入口函数(Main)中,Application.Run了我们在WUI库中创建的窗体(对于一个基于WUI库创建的程序来说,只有这么一个窗口),我们知道这个窗口的WebBrowser中没有任何东西,然而我们给WUIMain的属性PanelMain赋值了,这就是我们要添加的东西了

第四步:一个特殊的Panel

在上面的代码中,我们给PanelMain属性赋值为Main的实例,那么我们看一下Main是一个什么样的类型首先:这个类继承自PanelMain类,PanelMain类是WUI库提供的一个基类其次:这个基类中有一个事件叫OnRender,刚刚我们看到的JS方法中window.external.WUIPageLoaded();这行代码就会触发这个事件。

我们知道,一个用户界面上,有很多界面元素,这些界面元素装在一个容器中我们的Main类型就是最上层的容器,最上层的容器是一个特殊的容器,他的类型是PanelMain;(你们可能看到了,我们在OnRender事件中又添加了一个Panel,这个Panel就不是特殊的容器了,但这篇文章我们不讲这里)到此为止,我们有一个疑问,第一:什么时候触发的OnRender事件呢?这个时候我们就去看PanelMain的代码

看完PanelMain的代码我们疑问更多了: 第一:什么时候调用的Loaded方法呢? 第二:什么时候执行的ToJs方法呢?

第五步:C#与JS通信的开端

我们知道,我们在Program.cs中把Main类的实例交给了WUIMain窗口,那么这个窗口拿Main类的实例做了什么呢?让我们来看看WUIMain的代码

(说明一下WB就是我们的浏览器控件了)首先:我们让浏览器加载了那个主页文档(以后我们会做成动态的路径)第二:我们创建了一个RenderContext类的实例,并且把Main的实例交给类这个类型的构造函数第三:我们把浏览器的DomWindow赋值给了这个实例的IHTMLWin属性第四:我们把这个实例赋值给了浏览器的ObjectForScripting属性

这里有一点需要说明:要想使用IHTMLWindow2这个类型,必须要引用Mirosoft.mshtml这个扩展库(注意,要在“扩展”里去找),引用了这个扩展库之后,在名称空间那里加上这一行using mshtml;就可以使用IHTMLWindow2这个类型了

第六步:C#与JS通信的高潮

然而我们的疑问还是没有解决,那么只能继续看RenderContext的代码 首先:我们在这个类型的构造函数中得到了Main的实例 其次:我们把这个类型设置成了ComVisible (注意,要想设置一个类型为ComVisible,必须要使用System.Runtime.InteropServices;名称空间)

大家注意到了,这个类型里有一个公开的WUIPageLoaded方法,这个方法名是不是很眼熟呢?对了,就是我们在JS中调用的方法window.external.WUIPageLoaded(); 需要注意的有两点: 第一:一定要用window.external调用这个方法 第二:如果这个类型不设置成ComVisible就调用不到 第三:在WUIPageLoaded方法中,我们让浏览器执行了一段脚本,就是PanelMain的ToJs方法里的脚本了,这个时候就把这个控件渲染到浏览器中去了 第四:我们调用了PanelMain实例的Loaded方法,在那个方法里,我们触发了OnRender事件,这样我们的用户就知道什么时候他该接管接下去的工作了

注意: 在这里我们用C#让浏览器执行了脚本 浏览器用JS代码让我们的C#也做了工作 这就是C#和JS的通信了呢!

第七步:尾声

我们的程序看起来像这个样子 我当然知道这不是你想要看到的结果 那么,请您对这篇文章点个赞吧------------------------->> 您的支持是我写下一篇的动力!!!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏wOw的Android小站

[Android]相册列表加载过程性能优化

在手机中有多个存有图片的文件夹,在recent界面清掉所有的应用,点击进入图库,切换到相册列表。发现要过几秒钟才能从空白页面开始显示文件夹。同时会引起另一问题,...

37110
来自专栏python3

python代码风格

上面代码中----表示4个空格,如果用空格键去打,又长又多,很容易出问题,一个小技巧,用Tab代替4个空格,在Pycharm中默认Tab就是4个空格,不用去设置...

14930
来自专栏java 成神之路

编码规范

38290
来自专栏机器学习从入门到成神

Vue.js之组件及其易错点

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35512245/articl...

10010
来自专栏阮一峰的网络日志

关于URL编码

一般来说,URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号。比如,世界上有英文字母的网址"http://www.abc.com",但是没...

19630
来自专栏史上最简单的Spring Cloud教程

javascript入门笔记8-window对象

History 对象 history对象记录了用户曾经浏览过的页面(URL),并可以实现浏览器前进与后退相似导航的功能。 注意:从窗口被打开的那一刻开始记录,...

197100
来自专栏疯狂的小程序

微信小程序for循环里条件判断

今天踩了一下午的坑,但是确实很简单的问题。

50850
来自专栏Linux Python 加油站

Linux学习----文本三剑客——sed(马哥教育原创)

我以前的文章介绍过grep了,今天我就来说一下第二个sed,它是stream editor的缩写。在Linux的文本文件中文本存储都是一行,显示时表现的多行其实...

17230
来自专栏xingoo, 一个梦想做发明家的程序员

Windows下elasticsearch插入数据报错!

  按照官方文档操作,但是windows下有些不同,它不认识单引号',因此如果这样操作,就会报错: C:\Users\neusoft>curl localhos...

203100
来自专栏AI研习社

Bash 老司机也可能忽视的 10 大编程细节

AI 研习社按:Bash,作为大部分 Linux 发行版的出厂预设 Shell,因其晦涩难懂的语法设置,以及需要特别留心的编程细节,几乎成为 Linux 区别于...

29860

扫码关注云+社区

领取腾讯云代金券