多文档界面(MDI)系统框架-C#完整版(二)[vjsdn]

续多文档界面(MDI)系统框架-C#完整版(一)
http://www.cnblogs.com/raychn/archive/2010/07/23/1783520.html

前面讲了MDI程序设计概念和相关接口及类定义,并且实现了主窗体注册工具栏组件。通过上面详细介绍,我们
知道了主窗体与工具栏的互动关系,依赖关系和运作。那么,父窗体与子窗体之间互动是如何实现的呢?

我们先来分析子窗体的构成与未来无法预知的扩展。所谓扩展就是窗体特性化,个性化。A窗体有(a1,a2)功能,
B窗体不仅需要(a1,a2)还要(b1,b2)功能。假设(a1,a2)(b1,b2)是按钮集合的话?个性化特点就突出了!为下面
讲的窗体个性化埋下伏笔!子窗体是多样化的,初步分类有帮助窗体,数据编辑窗体,数据选择窗体,报表窗体,模式对话框,系统设置等等,这里无法枚举。不管有多少,统称子窗体。本着万物皆对象的原理,为何不抽象出一个IMdiChildForm的接口呢?

代码
/// <summary>
/// MDI子窗体的接口
/// </summary>
public interface IMdiChildForm
{
//子窗体的工具栏组件
IToolbarRegister ToolbarRegister { get;set; }

// 注册MDI窗体内的ToolBar.param mdiForm ToolBar管理对象的实例
void RegisterToolBar(IToolbarRegister toolBarRegister);

void RegisterObserver(IObserver[] observers); //注册子窗子观察者

IList Buttons {
get;} //返回窗体的按钮
void InitButtons(); //初始化窗体的按钮

bool IsClosing { get;set;} //窗体是否关闭状态
}

IMdiChildForm规范了子窗体的操作。RegisterToolBar()方法向父窗体的Toolbar注册按钮。InitButtons()
方法创建子窗体的按钮,通过Buttons属性可以获取。RegisterObserver()方法注册子窗子的观察者。
有了这些方法和属性父窗体与子窗体互动雏形出来了。

上面讲到窗体个性化要通过什么方式实现呢?
首先对子窗体分类,可以分系统公共,数据操作,报表窗体及锁定窗体4种基础类型。突出个性化无非是改变MDI父窗体的Toolbar按钮样式,所以定义4种接口来支持窗体操作的类型。
分别是ISystemButtons(系统公共),IDataOperatable(数据操作),IPrintableForm(报表窗体)。

ISystemButtons接口

代码
/// <summary>
/// 系统按钮
/// </summary>
public interface ISystemButtons
{
IButtonInfo[] GetSystemButtons();

void DoClose(IButtonInfo button); //关闭窗体
void DoHelp(IButtonInfo button); //打开帮助
}

IDataOperatable接口

代码
/// <summary>
/// 支持数据操作的接口
/// </summary>
public interface IDataOperatable
{
IButtonInfo[] GetDataOperatableButtons();
void DoViewContent(IButtonInfo button);//查看数据
void DoAdd(IButtonInfo button);
void DoEdit(IButtonInfo button);
void DoCancel(IButtonInfo button);
void DoSave(IButtonInfo button);
void DoDelete(IButtonInfo button);
}

IPrintableForm 支持打印功能的接口

代码
/// <summary>
/// 支持打印功能的接口
/// </summary>
public interface IPrintableForm
{
IButtonInfo[] GetPrintableButtons();

void DoPreview(IButtonInfo button);
void DoPrint(IButtonInfo button);
}

ILockableForm支持锁定/解除锁定功能的接口

代码
/// <summary>
/// 支持锁定/解除锁定功能的接口
/// </summary>
public interface ILockableForm
{
IButtonInfo[] GetLockableButtons();

void DoLock(IButtonInfo button);
void DoUnlock(IButtonInfo button);
}

子窗体接口定义完毕,接下来实现这些接口。
同时实现IMdiChildForm, ISystemButtons接口。

代码
public partial class frmBaseChild : Form, IMdiChildForm, ISystemButtons
{
private IToolbarRegister _ToolbarRegister = null; //父窗体的Toolbar组件
private IList _buttons = new ArrayList();//初始化数组
private IList _observers = new ArrayList();//子窗体观察者列表
private IButtonInfo[] _SystemButtons = null;//子窗体的按钮数组
private bool _IsClosing = false; //窗体是否正在关闭状态

public frmBaseChild()
{
InitializeComponent();
}

#region IMdiChildForm Members

public IToolbarRegister ToolbarRegister
{
get { return _ToolbarRegister; }
set { _ToolbarRegister = value; }
}

public virtual void RegisterToolBar(IToolbarRegister toolBarRegister)
{
//this.Buttons是当前窗体的按钮数组。
toolBarRegister.RegisterButton(this.Buttons);
}

//子窗体的按钮数组
public IList Buttons { get { return _buttons; } }

/// <summary>
/// 模板方法.初始化本窗体的按钮.
/// </summary>
public virtual void InitButtons()
{
IButtonInfo[] bi
= this.GetSystemButtons();
if (bi != null)
foreach (IButtonInfo btn in bi) _buttons.Add(btn);
}

/// <summary>
/// 系统按钮列表。注:子窗体享用系统按钮,如帮助/关闭窗体常用功能。
/// </summary>
public virtual IButtonInfo[] GetSystemButtons()
{
if (_SystemButtons == null)
{
_SystemButtons
= new IButtonInfo[2];
_SystemButtons[
0] = this.ToolbarRegister.CreateButton("btnHelp",
"帮助",
global::VJSDN.Tech.MDI.Properties.Resources._24_Help, new Size(57,
28), this.DoHelp);
_SystemButtons[
1] = this.ToolbarRegister.CreateButton("btnClose",
"关闭",
global::VJSDN.Tech.MDI.Properties.Resources._24_Exit, new Size(57,
28), this.DoClose);
}
return _SystemButtons;
}

public void DoHelp(IButtonInfo sender)
{
new frmAbout().ShowDialog();
}

public void DoClose(IButtonInfo sender)
{
this.Close();
}

#endregion

//子窗体获取焦点时注册子窗体的按钮。
//通过Form.Active我们可以看到主窗体的ToolBar动态变化。
private void frmBaseChild_Activated(object sender, EventArgs e)
{
this.RegisterToolBar(this.ToolbarRegister);
this.NotifyObserver(); //通过其它观察者
}

private void frmBaseChild_FormClosed(object sender, FormClosedEventArgs e)
{
NotifyObserver();
//当关闭窗体,要通知所有子窗体观察者
}

/// <summary>
/// 当前窗体是否正在关闭状态
/// </summary>
public bool IsClosing { get { return _IsClosing; }
set { _IsClosing = value; } }

/// <summary>
/// 注册子窗体观察者
/// </summary>
public void RegisterObserver(IObserver[] observers)
{
foreach (IObserver o in observers) _observers.Add(o);
}

//通知观察者进行更新
private void NotifyObserver()
{
foreach (IObserver o in _observers) o.Notify();
}

private void frmBaseChild_FormClosing(object sender, FormClosingEventArgs e)
{
this.IsClosing = true; //正在关闭状态
}
}

实现IDataOperatable接口

代码
/// <summary>
/// 数据操作窗体演示.
/// </summary>
public partial class frmChildData : frmBaseChild, IDataOperatable
{
private IButtonInfo[] _DataButtons = null;

#region IDataOperatable接口的方法

public IButtonInfo[] GetDataOperatableButtons()
{
//如果已经创建按钮,不要重复创建。
if (_DataButtons == null)
{
_DataButtons
= new IButtonInfo[6];
_DataButtons[
0] = this.ToolbarRegister.CreateButton("btnView",
"查看",
global::VJSDN.Tech.MDI.Properties.Resources._24_ViewContent, new Size(57, 28), this.DoViewContent);
_DataButtons[
1] = this.ToolbarRegister.CreateButton("btnAdd",
"新增",
global::VJSDN.Tech.MDI.Properties.Resources._24_Add, new Size(57, 28), this.DoAdd);
_DataButtons[
2] = this.ToolbarRegister.CreateButton("btnDelete",
"删除",
global::VJSDN.Tech.MDI.Properties.Resources._24_Delete, new Size(57, 28), this.DoDelete);
_DataButtons[
3] = this.ToolbarRegister.CreateButton("btnEdit",
"修改",
global::VJSDN.Tech.MDI.Properties.Resources._24_Edit, new Size(57, 28), this.DoEdit);
_DataButtons[
4] = this.ToolbarRegister.CreateButton("btnSave",
"保存",
global::VJSDN.Tech.MDI.Properties.Resources._24_Save, new Size(57, 28), this.DoSave);
_DataButtons[
5] = this.ToolbarRegister.CreateButton("btnCancel",
"取消",
global::VJSDN.Tech.MDI.Properties.Resources._24_Cancel, new Size(57, 28), this.DoCancel);
}
return _DataButtons;
}

//查看数据
public void DoViewContent(IButtonInfo sender)
{
MessageBox.Show(
"正在从数据库获取数据,然后显示....");
}

public void DoAdd(IButtonInfo sender)
{
this.SetEditMode();
MessageBox.Show(
"正在新增数据....");
}

public void DoEdit(IButtonInfo sender)
{
this.SetEditMode();
MessageBox.Show(
"正在Edit数据....");
}

public void DoCancel(IButtonInfo sender)
{
this.SetViewMode();
MessageBox.Show(
"Cancel完成.");
}

public void DoSave(IButtonInfo sender)
{
this.SetViewMode();
MessageBox.Show(
"Save完成.");
}

public void DoDelete(IButtonInfo sender)
{
MessageBox.Show(
"Delete完成");
}

#endregion
}

 实现IPrintableForm接口

代码
public partial class frmChildPrint : frmBaseChild, IPrintableForm
{
private IButtonInfo[] _PrintButtons = null;

public IButtonInfo[] GetPrintableButtons()
{
if (_PrintButtons == null)
{
_PrintButtons
= new IButtonInfo[2];
_PrintButtons[
0] = this.ToolbarRegister.CreateButton("btnPreview", "预览",
global::VJSDN.Tech.MDI.Properties.Resources._24_PrintPreview,
new Size(57, 28), this.DoPreview);
_PrintButtons[
1] = this.ToolbarRegister.CreateButton("btnDelete",
"打印",
global::VJSDN.Tech.MDI.Properties.Resources._24_Print, new Size(57,
28), this.DoPrint);
}
return _PrintButtons;
}

public void DoPreview(IButtonInfo sender)
{
MessageBox.Show(
"正在打开打印预览窗体...");
}

public void DoPrint(IButtonInfo sender)
{
MessageBox.Show(
"正在打印...");
}
}

实现ILockableForm接口

代码
public partial class frmChildLock : frmBaseChild, ILockableForm
{
private IButtonInfo[] _DataButtons = null;

public IButtonInfo[] GetLockableButtons()
{
//如果已经创建按钮,不要重复创建。
if (_DataButtons == null)
{
_DataButtons
= new IButtonInfo[2];
_DataButtons[
0] = this.ToolbarRegister.CreateButton("btnLock",
"锁定",
global::VJSDN.Tech.MDI.Properties.Resources._24_Lock, new Size(57, 28), this.DoLock);
_DataButtons[
1] = this.ToolbarRegister.CreateButton("btnUnlock",
"反锁定",
global::VJSDN.Tech.MDI.Properties.Resources._24_UndoBill,
new Size(57, 28), this.DoUnlock);
}
return _DataButtons;
}

public void DoLock(IButtonInfo button)
{
MessageBox.Show(
"已锁定单据!");
}

public void DoUnlock(IButtonInfo button)
{
MessageBox.Show(
"已经解除锁定!");
}
}

所有接口实现完毕,接下来是见证奇迹的时刻,请按f5.

 

 

代码
MdiTools 类

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using VJSDN.Tech.MDI.Interfaces;
using System.Runtime.InteropServices;

namespace VJSDN.Tech.MDI.Library
{
/// <summary>
/// 系统工具类
/// </summary>
public class MdiTools
{
//打开IE浏览器或打开Outlook
public static void OpenIE(string url)
{
//url= mailto:webadmin@vjsdn.com 打开Outlook
System.Diagnostics.Process.Start(url);
}

/// <summary>
/// 打开子窗体.
/// </summary>
/// <param name="mdi">MDI主窗体</param>
/// <param name="childFormClass">子窗体的名称空间</param>
public static void OpenChildForm(IMdiForm mdi, Type formType)
{
Form child
= ActiveChildForm(mdi as Form, formType.ToString());
if (child != null) return;
Form form
= (Form)formType.Assembly.CreateInstance(formType.FullName);
if (form != null && form is Form)
{
child
= form as Form;

if (form is IMdiChildForm)
{
(child
as IMdiChildForm).ToolbarRegister = mdi.MdiToolbar;
(child
as IMdiChildForm).RegisterObserver(mdi.MdiObservers);

child.MdiParent
= (Form)mdi;
child.Show();
}
else
{
child.Show();
}
}
else
throw new Exception("未知窗体类型!");
}

//如果是已经打开的窗体,激活即可.
public static Form ActiveChildForm(Form mdi, string formTypeName)
{
for (int x = 0; x < mdi.MdiChildren.Length; x++)
{
string ss = mdi.MdiChildren[x].GetType().ToString().ToUpper();
if (ss == formTypeName.ToUpper())
{
mdi.MdiChildren[x].Activate();
return mdi.MdiChildren[x];
}
}
return null;
}
}
}

 

 

 

/// <summary>
/// 观察者接口
/// </summary>
public interface IObserver
{
void Notify();
}

 

 

实现了3个观察者:

代码
/// <summary>
/// 观察用户是否关闭所有子窗体,如果用户关闭所有子窗体,显示MDI主窗体上的按钮
/// </summary>
public class ObserverCloseAllChild : IObserver
{
private Form _mdi = null;

public ObserverCloseAllChild(Form mdi)
{
_mdi
= mdi;
}

//如果用户关闭所有子窗体,显示MDI主窗体上的按钮
public void Notify()
{
if (_mdi.MdiChildren.Length == 0)
{
(_mdi
as IMdiForm).RegisterMdiButtons();
}
else if (_mdi.MdiChildren.Length == 1)
{
if (_mdi.MdiChildren[0] is IMdiChildForm)
{
if ((_mdi.MdiChildren[0] as IMdiChildForm).IsClosing)
(_mdi
as IMdiForm).RegisterMdiButtons();
}
}
}
}

/// <summary>
/// 观察当前子窗体,在MDI主窗体内显示子窗体的标题
/// </summary>
public class ObserverFormState : IObserver
{
ToolStripStatusLabel _label
= null;
private Form _mdi = null;

public ObserverFormState(Form mdi, ToolStripStatusLabel label)
{
_mdi
= mdi;
_label
= label;
}

public void Notify()
{
Form child
= _mdi.ActiveMdiChild;

if (child != null)
{
if (child is IMdiChildForm)
{
if ((child as IMdiChildForm).IsClosing)
_label.Text
= _mdi.Text;
else
_label.Text
= child.Text;
}
else
_label.Text
= child.Text;
}
else
_label.Text
= "没有打开子窗体.";
}
}

/// <summary>
/// 观察打个的窗体个数.
/// </summary>
public class ObserverOpenForms : IObserver
{
ToolStripStatusLabel _label
= null;
private Form _mdi = null;

public ObserverOpenForms(Form mdi, ToolStripStatusLabel label)
{
_mdi
= mdi;
_label
= label;
}

public void Notify()
{
//计算打开的子窗体个数,因Application.OpenForms.Count是所有打开的窗体数量,要减掉MDI主窗体.
int count = Application.OpenForms.Count - 1;
if (count < 0) count = 1;
_label.Text
= string.Format("共打开{0}个窗体", count);
}
}

 

 

未完,后续(UML建模)....

 

==============================

多文档界面(MDI)系统框架已完成。链接地址:

系统介绍及接口设计
多文档界面(MDI)系统框架-C#完整版(一)

父窗体与子窗体之间互动关系及Toolbar实现
多文档界面(MDI)系统框架-C#完整版(二)

系统框架UML图
多文档界面(MDI)系统框架-C#完整版(三)(UML图)

posted on 2010-07-23 10:53  raychn  阅读(2886)  评论(0编辑  收藏  举报