• Windows Forms(二)


    导读

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

    2、分析上面的程序

    3、Mediator pattern(中介者模式)

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


    用VS创建一个Windows Forms程序

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

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

    image

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

    image

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

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

    运行效果为:

    image

    分析上面的程序

    image

    我们关注红框中的.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(206, 9);
                this.button1.Name = "button1";
                this.button1.Size = new System.Drawing.Size(75, 23);
                this.button1.TabIndex = 0;
                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(12, 10);
                this.textBox1.Name = "textBox1";
                this.textBox1.Size = new System.Drawing.Size(188, 21);
                this.textBox1.TabIndex = 1;
                // 
                // Form1
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(288, 39);
                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

    直接上代码

    image

    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

    运行效果

    image

    源码下载

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

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

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

    卡UI怎么办——BackgroundWorker组件

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

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

    先看下效果

    image

    代码下载

    本文完

  • 相关阅读:
    2.1 JavaScript应用开发实践指南
    2 JavaScript应用开发实践指南
    一 JavaScript应用开发实践指南
    工作“触雷”经历与总结--记博弈论的应用
    设计模式之 简单工厂,工厂方法,抽象工厂
    C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是TAP(Task-based Asynchronous Pattern, 基于任务的异步模式)
    C语言知识结构
    Visual Studio 项目和解决方案 路径修改(解决部分模板丢失的问题)
    C#静态方法和实例方法的内存分配测试
    Java字符串String
  • 原文地址:https://www.cnblogs.com/Aphasia/p/4355728.html
Copyright © 2020-2023  润新知