从这一篇开始要讲管控端是如何来加载菜单与工具栏的了,.Net Framework自带的菜单与工具栏用来做一个简单的小程序是大大胜任的。但用它们来实现一个可以称之为系统的东西则不够强大,变化多端的环境转瞬间就使它们的功能是捉襟见肘了,这里我们必须先要对它们做出一定的改造。
菜单与工具栏只是UI的二种不同表现,二者在系统的动作执行上是没有什么不同的。由此说起二者的系统集成,一般都会提到Command这个设计模式,我这里当然也逃不出那个模子。
在.Net里没有如Delphi那样提供有一个TCustomAction之类的东西,那只有自己定义一个接口:
public interface ICommand
{
string ID { get;set;}
void Execute();
}
简单点,什么Undo,Enabled都不用了,只有一个Execute这么一个动作及一个标识。
为了把动作与具体的UI元素分离,再定义一个接口:
public interface ICommandHolder
{
ICommand GetCommand();
void SetCommand(ICommand cmd);
}
其实就是一个属性,以后只要我们的菜单(或按钮)类实现了ICommandHolder这个接口,那就可以了。
下面来提取我们这个系统中需要的Command。在这个系统中动作主要有二类,一是执行动作后调出一个新的窗体,二是执行动作后并没有新窗体出现(可能会改变当前UI的某些元素。对于这二类动作,其Execute方法是不同的,所以这里分为二个类来实现不同的动作。
对于显示窗体的Command:
反射无处不在。而对于没有新窗体出现的Command,原理也是差不多的,只是构造出相应类型后,执行相关的动作。
Type frmType = Type.GetType(formType);
//执行命令的类要实现singleton模式
object objFrm = frmType.InvokeMember("getInstance",
BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod,null,null,new object[] {owner});
if (methodName.Length > 0)
{
frmType.InvokeMember(methodName,
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,null,objFrm,null);
}
由于对于相似的一组命令执行类,它们之间类成员没有什么异同,所以它们之间共享同一实例,这里注释上写“要实现singleton模式”,其实到具体实现时由于环境的特殊关系,这个“singleton模式”有时也不是我们通常的那种写法。