C# winForm类似CAD命令的处理方法
仿CAD命令实现目标:在窗体中,有一可供用户输入命令的文本框te_Command,用户输入命令后按回车/空格,窗体可以执行相应的方法。
传统思路是在te_Command的KeyUp事件订阅器里使用switch(te_Command.Text){},但是这种方法当命令多了以后,代码的可读性和可扩展性都不是很好,改起来也比较麻烦。
解决思路:
1、创建一个自定义特性类,用于标识方法对应的命令和功能名称:
/// <summary> /// 命令处理方法特性 /// </summary> [AttributeUsage(AttributeTargets.Method)] public class DcHandlerAttribute : Attribute { /// <summary> /// 对应的命令文本字符串数组 /// </summary> public string[] CommandText { get; set; } /// <summary> /// 对应的功能名称 /// </summary> public string FcName { get; set; } /// <summary> /// 默认构造函数 /// </summary> /// <param name="commandText">命令文本字符串数组</param> /// <param name="fcName">功能名称</param> public DcHandlerAttribute(string[] commandText, string fcName) { CommandText = commandText; FcName = fcName; } }
2、创建一个命令功能名称和委托的类,用于存储功能名称和其对应的方法的委托:
/// <summary> /// 命令功能名称和处理方法委托类 /// </summary> public class Cl_CommandHandler { /// <summary> /// 功能名称 /// </summary> public string FcName { get; set; } /// <summary> /// 处理方法的委托 /// </summary> public Action Handler { get; set; } /// <summary> /// 默认构造函数 /// </summary> /// <param name="fcname">功能名称</param> /// <param name="handler">处理方法的委托</param> public Cl_CommandHandler(string fcname, Action handler) { FcName = fcname; Handler = handler; } }
3、在窗体中设置一个字典
public Dictionary<string, Cl_CommandHandler> CommandHandlerDic;
4、创建上述字典,此方法在窗体的构造函数中调用。
/// <summary> /// 使用反射技术,自动探测含有特定特性的方法,初始化命令、委托对应字典 /// </summary> private void InitializeCommandHandler() { //初始化命令字典 CommandHandlerDic = new Dictionary<string, Cl_CommandHandler>(); //取得fm_Design类的所有私有动态方法 foreach (var m in typeof([当前窗体类名]).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)) { //取得方法的特性 var atts = m.GetCustomAttributes(); if (atts.Count() > 0) { foreach (var item in atts) { if (item is DcHandlerAttribute att) { //命令字符串数组 var ctext = att.CommandText; //功能名称 var fcname = att.FcName; //创建私有方法的Action委托 var a = Delegate.CreateDelegate(typeof(Action), this, m) as Action; var dch = new Cl_CommandHandler(fcname, a); //添加或修改命令、委托对应数组 for (int i = 0; i < ctext.Length; i++) { if (!CommandHandlerDic.ContainsKey(ctext[i])) CommandHandlerDic.Add(ctext[i], dch); else CommandHandlerDic[ctext[i]] = dch; } }//包含命令处理特性时 }//遍历特性 }//包含特性时 }//遍历所有方法 }
5、te_Command的键抬起处理方法
/// <summary> /// 命令栏KeyUp事件初始处理方法 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void te_Command_KeyUp(object sender, KeyEventArgs e) { //抬起回车键或空格键 if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Space) { te_Command.Text = te_Command.Text.Trim().ToUpper(); var commandText = te_Command.Text; if (string.IsNullOrEmpty(commandText)) return; if (CommandHandlerDic.ContainsKey(commandText)) { //执行委托 CommandHandlerDic[commandText].Handler(); } te_Command.Text=""; } //Esc键 else if (e.KeyCode == Keys.Escape) { te_Command.Text = ""; } }
6、这样以后想增加某个命令时,只需要在方法前加上自定义特性即可:
[DcHandler(new string[] { "ST", "START" }, "初始化")] private void Dch_Start() { //具体实现代码... } [DcHandler(new string[] { "BACK" }, "关闭")] private void Dch_Back() { //具体实现代码... } [DcHandler(new string[] { "?", "H", "HELP" }, "帮助")] private void Dch_Help() { //具体实现代码... } [DcHandler(new string[] { "EXIT", "QUIT" }, "退出")] private void Dch_Quit() { //具体实现代码... }
构建窗体时,会自动检查含有自定义特性的方法,然后建立命令字符串-委托的字典。当用户在te_Command里输入命令后,程序会在字典里寻找对应的委托来执行。
当然还需要另外一个显示命令执行情况的文本框。

浙公网安备 33010602011771号