多文档界面(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图)