前言
我有一个习惯,在学一个东西的时候总想着尽量详细的掌握和它相关的所有概念,再用简单的话来描述它。好处在于了解的确实多,感觉什么都懂一点,但是太容易忘,也太费劲了。还有一点在于,牵扯出来的东西我似乎永远无法全部掌握,总有新的名词、新的技术冒出来,像窗台上的灰尘,或是反复出现的胡子渣。我想从当前的状态里挪出去几步,尽可能深入的去了解一个领域、一项技能,多而不精很容易,专精则要难很多。这不表示着不去接收新的领域,我觉得,在真正掌握一种技术后,再去以那样的视角学习其他技术要更加得心应手。
拿现在的项目来说,要具体操手项目,起码得看懂并且修改续写项目代码,这需要对 Winform 进行系统性的学习,同时 C# 语言的进度也不能丢。由于其特性涉及到了.net 领域相关技术,这一过程中则必然的延伸到了 java script。以我目前的了解,这个领域的范围到这里基本上可以有了确定的界限,因此现阶段的目标就是跑通项目流程,把 C# 和 Winform 在已有基础上深入学习,大体掌握后再开始对 java 相关的问题进行学习。这样的规划基本程度上能让我对三大块语言都有一定的基础(我的理解是 python、java 以及 c 系列属于主流三大块),后续再针对项目过程中学习到的相关知识加以深入研究(网络协议等)。编程方面,我并没有太多基础可言,相较于计算机专业的学生还有一定的差距,因此还是需要尽快通过项目任务来缩短距离。如果再往后拓展,那么我也想去回过头学习学习硬件,尽可能多的接触一些领域,在择业的时候也能有更多想法。
这里再插一嘴,之前一直以为项目文件是采用的 wpf 实现的,知道今天学习 wpf 才发现不对劲。经过查证才知道是 winform 项目,实在是太乌龙了。Winform 和 WPF 同属应用程序设计,最大的区别在于布局方式和驱动方式:
- 一般来说,界面布局的方式有两种,一种是拖控件,另一种是通过布局控件来实现,而 Winform 主要是以拖控件的方式为主,配合布局控件做整体布局,而 WPF 则恰恰相反,虽然也可以拖控件,但是很少这么做,主要是通过编写 XAML 代码来实现。
- 驱动方式方面,Winform 是基于事件驱动,WPF 是基于数据驱动,以操作一个按钮,执行一个查询操作为例,Winform 是在按钮的点击事件里,写好查询代码,然后将结果展示在数据控件里,而WPF 则是通过按钮绑定一个动作方法,数据控件绑定好数据源,在方法里查询即可,这样做的目的就是尽量减少前后端的耦合。
MVVM、MVC、MVP
谈到学习 Winform 的开发,就必须要学习 MVVM ,学习 MVVM ,就要首先了解 MVC、MVP 等概念。不论是 MVP 还是 MVVM,,基础都在于 MVC。
MVC 的全称即 Model-View-Controller,核心是三层模型 Model-View-Control 。它是一种客户端软件开发框架,view 负责显示,model 负责提供数据,controller 则负责逻辑的处理,实现流程大概如下:
- 当用户需要发送请求时,首先是在 View 发送请求,由 View 将指令传送到 Controller 里。
- Controller 接收到指令之后,先完成所需要的业务逻辑,然后要求 Model 根据业务逻辑改变状态。
- Model 将新的数据发送给 View,View 则根据新的数据更新视图,从而用户的请求得到反馈。
在 MVC 框架中,View 是可以直接访问 Model 的,这样不可避免的使 View 里面也需要包括一些业务逻辑,同时还需要 Model 保持不变,而 Model 又对应着多个不同的显示(View),所以总体说来就是,在 MVC 模型里面,Model 不依赖 View,但是 View 是依赖于 Model 的。这样就导致更改 View 比较困难,且业务无法重用。从而 MVC 框架的弊端就显现出来,前后端没有解耦,Model与View没有彻底解耦。(解耦,字面意思就是解除耦合关系,接触两者间的相关关系。)
为了解决 MVC 框架中 View 和 Model 联系紧密的问题,开发者研究开发了 MVP 模式,MVP 即 Model-View-Presenter,即把 MVC 中的 Controller 换成了 Presenter,目的就是为了完全切断 View 跟 Model 之间的联系,在 MVP 模式中,View 负责视图的显示,Model 负责提供数据,Presenter 则主要负责逻辑业务的处理。Presenter 与 View 也是没有直接相关联的,而是通过已定义的接口进行交互,从而使得在变更 View 的时候可以保持 Presenter 的不变,即保证了 Presenter 的可重用性(接口的复用性),同时也解决了 MVC 框架中的 View 和 Model 关联紧密的问题。
对于大型项目而言,前端的东西原来越多,造成服务端的压力越来越大,而且由于MVP的出现,逐渐向前后端分离靠拢,分离之后,View 分担服务端的压力,或者说是浏览器分担了服务器压力,包括页面渲染,路由等问题,这时侯 MVVM 出现了。(推测说法)MVVM 框架便是前后端分离框架发展史上的一次思想的完全变革。它是将数据模型双向绑定的思想作为变革的核心,即 View 的变动,自动反映在 ViewModel 上面,而 ViewModel 的变动也会随即反映在 View 上面,从而实现数据与模型的双向绑定。
在 MVVM 框架中,View 用于发送用户的交互请求,之后将用户请求转交给 ViewModel,ViewModel 即可根据用户请求操作 Model 数据更新,待 Model 数据更新完毕,便会通知 ViewModel 数据发生了变化,然后 ViewModel 就会即刻更新 View 数据,完成视图的更新,从而完成用户的请求。
虽然MVVM框架和之前的 MVC、MVP 式的目的相同,即完成视图(View)和模型(Model)的分离,但它却有着明显的优势:- 首先,MVVM 框架中的 View 完全可以独立于 Model 发生变化和修改,彻底解耦,View 发生变化时 Model 可以不变,同样,当 Model 发生变化时 View 也可以不变化,并且一个 ViewModel可以绑定到多个不同的 View 上面,这就体现了 MVVM 框架的低耦合性。
- 其次,绑定在一个 ViewModel 上面的多个 View 都可以使用 ViewModel 里面的视图逻辑,完成了框架可重用性的特性。除此之外,MVVM 框架还具有可独立开发、可测试等特性,把框架作用发挥到最大化,也因此成为了开发者们青睐的框架。
以上内容仅是初步介绍,很多内容并没有深入探讨,主要是我看的也似懂非懂,感觉还需要具体实操后才能更深入了解。暂且搁置,学习完成后再回过头来深入解析。
Winform基础信息
Winform 文件结构如下所示:
- 引用:包括所有的系统库文件的引用依赖(外部库)
- App.config:当前项目的配置文件
- Form1.cs:当前窗体的事件逻辑源码
- Form1.Designer.cs:当前窗体的控件布局源码
- Form1.resx:当前窗体的资源文件(图片、图标、资源等)
!Form1.cs 和 Form1.Designer.cs 都定义了 Form1 类,该类使用了 Partial 关键词声明,其定义的类可以在多个地方被定义,最后编译的时候会被当作一个类来处理。因此两个文件各司其职,最后合并为一个类编译。
!要手动实现自定义窗体,可以添加自己的类,然后继承 Form 类即可
- Program.cs:当前项目程序的主入口 Main,启动项目,运行初始窗口
窗体设计与控件布局:
在设计界面拖拽控件,可以完成界面布局(控件大小、名称、类型、样式等),设计界面自动关联 Form1.Designer.cs 文件,在 InitializeComponent() 方法中会自动生成相关代码。
设计原则:
- Form1.Designer.cs 文件:窗体控件布局文件,一般**不需要修改**,只要通过设计界面代码就会自动生成。
- Form1.cs 文件:窗体事件逻辑代码的实现,一般**需要手动书写**,包括触发事件、回调、数据交互、跳转等等
手动添加控件,不通过设计界面,有两种方式:
- 在 orm1.Designer.cs 中添加:
1 | private System.Windows.Forms.Button btn_design;//声明控件 |
- 在 Form1.cs 中添加:
1 | private Button btn_design;//声明控件 |
注意点:
一般情况都使用拖拽添加控件,当然也有特殊情况需要手动添加(比如自定义控件)。
窗体 GUI 中,左上角为原点(0,0),竖直向下为y轴,水平向右为x轴(宽度表示 x 轴上长度,高度表示 y 轴上长度),单位为像素。
窗口设计:
WinForm 自动添加事件处理:
(1)操作:在设计界面-控件属性-闪电符号(事件)-添加事件,就会在 Form1.cs 中自动生成该控件相应方法名称的事件触发函数
(2)MessageBox.Show():显示弹出消息提示框
(3)GUI 界面下 Console.WriteLine 不显示,需要使用调试模式
1 | namespace WindowsFormsApp_learning |
WinForm 手动添加事件处理:
(1)添加按钮控件到布局
(2)书写事件处理函数,必须符合 void function_name(object param1,EventArgs e){} 的形式
(3)添加注册事件,this.Btn_design.Click += new EventHandler(this.showTip)
1 | namespace WindowsFormsApp_learning |
一般情况下自动添加事件就好,除非有自定义等情况。自动添加时注意控件在 vs 左面的工具箱中,拖动控件到 ui 界面后,点击对应控件后在右下角便有控件事件,通过控件事件即可定义功能。控件事件及属性如下图所示: