导读

1、用VS创建一个Windows Forms程序

2、分析上面的程序

3、Mediator pattern(中介者模式)

4、卡UI怎么办——BackgroundWorker组件


用VS创建一个Windows Forms程序

博主应为项目需要用的VS2005,所以这个系列的Windows Forms 特指Windows Forms 2.0。

打开VS2005 –> 建立 Windows应用程序,过程截图如下(其实这种简单的步骤,做C#开发都会)

拖拽一个Button 和 TextBox 控件,界面如下

双击Button控件添加Click事件,代码如下:

private void button1_Click(object sender, EventArgs e)
{
this.textBox1.Text = "Windows Forms (二) By Aphasia";
}

运行效果为:

分析上面的程序

我们关注红框中的.cs 文件,这是C#源代码文件,至于.resx那是资源文件,我们现在不需要关注。上面有3个.cs 文件(3个C#源代码)。我们先看 Program.cs

using System;
using System.Collections.Generic;
using System.Windows.Forms; namespace WinFormDemo
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

默认引用了3个命名控件(这个可以通过修改VS的模板来修改默认引用的命名空间) 继续往下看

静态类 Program 下有一个Main方法,Main方法上有一个 STAThread 的特性(Attribute)(含义是单线程模型,这个我们暂时不需要关心,我们以后会谈到,这里我们只需要了解就可以了)。Main方法里有3行代码,这3行代码在前一篇Windows Forms的博客中提到过

Application.EnableVisualStyles(); 开启WinXp的样式

Application.SetCompatibleTextRenderingDefault(false); 设置文本的现实方式(是GDI+还是GDI,这个我们以后将System.Drawing时会提到,这里暂时了解即可)

Application.Run(new Form1());  在当前AppDomain中加载 Form1窗体

再看 Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms; namespace WinFormDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
this.textBox1.Text = "Windows Forms (二) By Aphasia";
}
}
}

默认命名控件跳过

看到 窗体类 Form1 前面有个关键字 partial,这个关键字的含义是分布类是.NET 2.0 引入的一个语法糖,含义是将一个类的定义分布在多个源码文件(.cs 中),好处嘛就是扩展性加强有利于前后台分离,继续往下看构造器

构造器中调用了  InitializeComponent 方法(中文含义是初始化组件),奇怪的是这个方法的定义没在Form1.cs 中尼,那它在哪尼?别急继续往下看

私有方法 button1_Click 参数类型有点像前一篇谈到 System.EventHandler 委托的原型定义

我们再看 Form1.Designer.cs

namespace WinFormDemo
{
partial class Form1
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null; /// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
} #region Windows 窗体设计器生成的代码 /// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(, );
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(, );
this.button1.TabIndex = ;
this.button1.Text = "Click Me";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(, );
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(, );
this.textBox1.TabIndex = ;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(, );
this.Controls.Add(this.textBox1);
this.Controls.Add(this.button1);
this.MaximizeBox = false;
this.Name = "Form1";
this.Text = "用VS建第一个WinForm程序";
this.ResumeLayout(false);
this.PerformLayout(); } #endregion private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox1;
}
}

乖乖,这个编译器生成的代码真多 。我们看到这个类也是一个分布类,这里定义了InitializeComponent 方法,所以在Forms.cs 中就直接可以调用了。我们看下InitializeComponent 的内容

Button控件和TextBox控件的初始化及赋值 注意 SuspendLayoutResumeLayoutPerformLayout这个两个方法的含义是挂了控件的布局逻辑与恢复布局逻辑,有点类似SQL中事务的逻辑 Begin tran … 各种增删改查 … commit tran的逻辑

Button 和 TextBox 是控件类,这里做私有字段

还有一个东西需要提下

private System.ComponentModel.IContainer components = null;

components 这是干嘛的?其实把这货删掉了我们的这个Demo也能跑起来(把Dispose 方法中对这货的引用注释掉)那编译器干嘛还有生成这货尼。原因是这样的,当我们引用一些设计时可见,运行时不可见的组件时,这货就有用了,在Dispose方法中释放一些非托管资源,对于初学Windows Form的朋友现在只需要了解即可,再后续的博文会详谈的。

对比我在前一篇写的程序,我把窗体绘制逻辑和AppDomain运行分离到两个类中,VS比我更进了一步,它将窗体绘制逻辑用分布类这个机制再分成两个源代码文件 ——一个设计时由VS生成的Form1.Designer.cs,以后后台类 Form1.cs。这是一种进步

Mediator pattern(中介者模式)

上面的Demo程序代码分析差不多了,我们来看一个设计模式 Mediator pattern(中介者模式)

我们先看 Wiki上定义

In Software Engineering, the mediator pattern defines an object that encapsulates how a set of objects interact. It promotes loose coupling by keeping objects from referring to each other explicitly, and it allows their interaction to be varied independently.Client classes can use the mediator to send messages to other clients, and can receive messages from other clients via an event on the mediator class.

白话一下:中介者模式定义了一个中介者类来封装各个对象的交互,这个模式保证了各个对象之间交互的松耦合(因为他们之间的交互是通过中介,各个对象之间也许都不知道各个对象的存在,好比你去通过中介租房的流程一样,你只知道有个中介,不一定知道房东是谁。下面我就以租房的例子来写一个Demo)

我们分析下需要写那些东西(由于这个笔记本没有装UML建模软件,现在没法画UML图,各位看客先凑合着看,后面补上)

一个中介类

一个房东和房客的基类

上面的两个都是抽象类

具体的中介类1

具体的房东类1

具体的房客类1

直接上代码

BaseZhongjie.cs

namespace WinFormDemo
{
public abstract class ZhongJie
{
public abstract void SendMsg(BasePerson person,string msg);
}
}

BasePerson.cs

namespace WinFormDemo
{
public abstract class BasePerson
{
// 房东与房客的共同点就是他们都知道中介,也就是他们应该有中介这个字段
protected ZhongJie zhongJie;
public BasePerson(ZhongJie zhongJie)
{
this.zhongJie = zhongJie;
}
}
}

FangDong.cs

namespace WinFormDemo
{
public class FangDong : BasePerson
{
public FangDong(ZhongJie zhongjie) : base(zhongjie)
{} // 向中介发布房源信息
public void Send(string msg)
{
base.zhongJie.SendMsg(this,msg);
} // 房东收到中介给予的消息
public void Notify(string msg)
{
System.Console.WriteLine("房东收到消息 {0} ",msg);
}
}
}

FangKe.cs

namespace WinFormDemo
{
public class FangKe : BasePerson
{
public FangKe(ZhongJie zhongjie) : base(zhongjie)
{} // 向中介发布求租信息
public void Send(string msg)
{
zhongJie.SendMsg(this,msg);
} // 房客收到中介给予的消息
public void Notify(string msg)
{
System.Console.WriteLine("房客收到消息 {0} ",msg);
}
}
}

ZhongJieA.cs

namespace WinFormDemo
{
public class ZhongJieA : ZhongJie
{
// 中介这注册了多个房东和房客信息
private FangDong fangDongA;
private FangKe fangKeA; public FangDong FangDongA
{
get{return fangDongA;}
set{fangDongA = value;}
}
public FangKe FangKeA
{
get{return fangKeA;}
set{fangKeA = value;}
} public override void SendMsg(BasePerson person,string msg)
{
#region 中介转发消息
if(person is FangDong)
{
if(fangKeA != null)
{
// 有房客在求租,中介给房客发送可以看房的信息
fangKeA.Notify("房东有房要出租,你可以去看房了。。。");
}
}
if(person is FangKe)
{
if(fangDongA != null)
{
fangDongA.Notify("有个小伙子想租你的房子,你看你什么时候有空我带他去看房");
}
}
#endregion
}
}
}

build.bat

csc /out:BaseLib.dll /t:library BasePerson.cs BaseZhongjie.cs
csc /out:Lib.dll /r:BaseLib.dll /t:library FangDong.cs FangKe.cs ZhongJieA.cs
csc /r:BaseLib.dll,Lib.dll App.cs

运行效果

源码下载

中介者模式讲完了,中介者模式和Windows Forms 有什么关系尼?其实Windows Forms 就用到了中介者模式, Form 窗体是中介者,各个控件如Button和TextBox就是上面的房东或房客,他们彼此不一定知道对方的存在,但是知道有窗体存在

Button 捕获了鼠标单击,委托给窗体(中介者)里的方法button1_Click执行,这个方法里通知 TextBox显示我们需要显示的内容。

从上面了流程来看Button根本就不需要知道有TextBox的存在,它只是委托出去单击的执行。

卡UI怎么办——BackgroundWorker组件

文章最后的给出一个 BackgroundWorker 的例子

我们用Thread.Sleep 模式后台卡UI,用进度条反应卡UI的操作完成了百分之多少

先看下效果

代码下载

本文完

Windows Forms(二)的更多相关文章

  1. .net chart(图表)控件的使用-System.Windows.Forms.DataVisualization.dll

    这个案例指在介绍微软这套免费又功能强大的图表控件Microsoft Chart Controls for Microsoft .NET Framework 3.5,通过它,可让您的项目及报表,轻松套用 ...

  2. System.Windows.Forms.Timer

    一.主要属性.方法和事件 Windows 窗体 Timer 是定期引发事件的组件.该组件是为 Windows 窗体环境设计的. 时间间隔的长度由 Interval 属性定义,其值以毫秒为单位.若启用了 ...

  3. C#在父窗口中调用子窗口的过程(无法访问已释放的对象)异常,不存在从对象类型System.Windows.Forms.DateTimePicker到已知的托管提供程序本机类型的映射。

    一:C#在父窗口中调用子窗口的过程(无法访问已释放的对象)异常 其实,这个问题与C#的垃圾回收有关.垃圾回收器管 理所有的托管对象,所有需要托管数据的.NET语言(包括 C#)都受运行库的 垃圾回收器 ...

  4. 从零开始学Xamarin.Forms(二) 环境搭建、创建项目

    原文:从零开始学Xamarin.Forms(二) 环境搭建.创建项目 一.环境搭建 Windows下环境搭建:     1.下载并安装jdk.Android SDK和NDK,当然还需要 VS2013 ...

  5. Oracle 远程访问配置 在 Windows Forms 和 WPF 应用中使用 FontAwesome 图标 C#反序列化XML异常:在 XML文档(0, 0)中有一个错误“缺少根元素” C#[Win32&WinCE&WM]应用程序只能运行一个实例:MutexHelper Decimal类型截取保留N位小数向上取, Decimal类型截取保留N位小数并且不进行四舍五入操作

    Oracle 远程访问配置   服务端配置 如果不想自己写,可以通过 Net Manager 来配置. 以下配置文件中的 localhost 改为 ip 地址,否则,远程不能访问. 1.网络监听配置 ...

  6. Wizard Framework:一个自己开发的基于Windows Forms的向导开发框架

    最近因项目需要,我自己设计开发了一个基于Windows Forms的向导开发框架,目前我已经将其开源,并发布了一个NuGet安装包.比较囧的一件事是,当我发布了NuGet安装包以后,发现原来已经有一个 ...

  7. windows forms 上一个类似于wpf snoop 的工具: Hawkeye

    windows forms 上一个类似于wpf snoop 的工具: Hawkeye 周银辉 WPF上有snoop这样的run time object editor让人用着很爽, 今天搜到了一个for ...

  8. WPF中实例化Com组件,调用组件的方法时报System.Windows.Forms.AxHost+InvalidActiveXStateException的异常

    WPF中实例化Com组件,调用组件的方法时报System.Windows.Forms.AxHost+InvalidActiveXStateException的异常 在wpf中封装Com组件时,调用组件 ...

  9. DotNetBar for Windows Forms 12.9.0.0_冰河之刃重打包版及制作Visual Studio C#项目模板文件详解

    关于 DotNetBar for Windows Forms 12.9.0.0_冰河之刃重打包版 --------------------11.8.0.8_冰河之刃重打包版-------------- ...

随机推荐

  1. 使用CSS3和jQuery可伸缩的搜索条

    使用CSS3和jQuery可伸缩的搜索条 helloweba.com 作者:月光光 时间:2013-12-09 21:23 标签: CSS3 jquery 搜索条在我们网站是必不可少的,尤其是在有限的 ...

  2. Python中如何把一个UTC时间转换为本地时间

    需求: 将20141126010101格式UTC时间转换为本地时间. 在网上搜了好长时间都没有找到完美的解决方案.有的引用了第三方库,这就需要在现网安装第三方的软件.这个是万万不可的.因为真实环境不一 ...

  3. JavaScript 要点(十四)HTML DOM 元素(节点)

    A.创建新的 HTML 元素 如需向 HTML DOM 添加新元素,必须首先创建该元素(元素节点),然后向一个已存在的元素追加该元素. <div id="div1"> ...

  4. Android设计模式系列--模板方法模式

    模板方法,和单例模式是我认为GOF的23中最简单的两种模式.但是我个人对模板方法的经典思想特别推崇,虽然模板方法在大对数情况下并不被推荐使用,但是这种通过父类调用子类的方法,使用继承来改变算法的一部分 ...

  5. 传微软欲收购Xamarin:未来有望通过VS开发iOS和Android应用?

    据CRN报道,其援引匿名人士的消息称,微软将收购一家创建C#移动应用工具的公司或进行注资,并且谈判已经到了最终阶段.这家公司的名字叫做Xamarin,创建于2011年.对于微软来说,收购Xamarin ...

  6. forward_list例子

    9.28 编写函数,接受一个forward_list<string>和两个string共三个参数.函数应在链表中查找第一个string,并将第二个string插入到紧接着第一个string ...

  7. 文件I/O(不带缓冲)概述

    一.引言 UNIX系统中大多数文件I/O只需用到5个函数:open.read.write.lseek以及close.这些函数经常被称为不带缓冲的I/O(unbuffered I/O).术语不带缓冲指的 ...

  8. QT: QByteArray储存二进制数据(包括结构体,自定义QT对象)

      因为利用QByteArray可以很方便的利用其API对内存数据进行访问和修改, 构建数据库blob字段时必不可少; 那如何向blob内写入自定义的结构体和类 1. 利用memcpy拷贝内存数据 / ...

  9. Day03 - Python 函数

    1. 函数简介 函数是组织好的,可重复使用的,用来实现单一或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.Python提供了许多内建函数,比如print():也可以自己创建函数,这 ...

  10. Java基础知识强化之网络编程笔记11:TCP之TCP协议上传文本文件

    1. TCP协议上传文本文件(客户端上传数据到服务器端) (1)客户端(上传数据到服务端) package cn.itcast_11; import java.io.BufferedReader; i ...