C#趣味小程序(6)——动态工具栏

问题描述:是将MenuStrip中的所有DropDownItems列出来,供用户选择,被选中的项将在ToolStrip被显示出来,并且可以使用与其对应的DropDownItem的事件. 其工作流程可以分解如下图所示: 图1.1流程图实际上这个图所描述的正是我们上面说的一样,只是换作图形表示而已,但这样一来程序的结构就变得清晰起来了。         实际上这个图所描述的正是
摘要由CSDN通过智能技术生成

问题描述:

是将MenuStrip中的所有DropDownItems列出来,供用户选择,被选中的项将在ToolStrip被显示出来,并且可以使用与其对应的DropDownItem的事件.

其工作流程可以分解如下图所示:

 

图1.1流程图

实际上这个图所描述的正是我们上面说的一样,只是换作图形表示而已,但这样一来程序的结构就变得清晰起来了。

         实际上这个图所描述的正是我们上面说的一样,只是换作图形表示而已,但这样一来程序的结构就变得清晰起来了。可以看出,整个问题实际上被分解成了三个部分,即遍历菜单栏所有可用的DropDownItems,提供用户的选择界面,和为工具栏动态添Items及其事件。提供用户的选择界面这部分内容没什么技术含量,可以用任何一种你喜欢的方式实现,没什么好说的。下面我将重点说一下遍历菜单栏所有可用的DropDownItems,和为工具栏动态添Items及其事件这两部分。

一、  遍历菜单栏所有可用的DropDownItems

菜单栏的结构实际上是典型的森林,而每一个下拉菜单(DropDownItem)都是一棵树。面对这种问题最好的解决方式就是递归。很多人提到递归就头大,其实对于了解递归的人来说递归很简单。尤其是树的遍历就更加的简单了,它有固有的模式,一般先对结束条件进行判断,然后递归遍历各个子树,就这么简单。对于本题DropDownItem的函数可以这样来写:

        private ToolStripMenuItem Items(ToolStripMenuItem tsItem)

        {    //结束条件判定

            if (tsItem.DropDownItems.Count <= 0) return tsItem;

            else

            {    //遍历各子树

                foreach (ToolStripMenuItem mItem in tsItem.DropDownItems)

                {    //递归遍历mItem子树

                    Items(mItem);

                }

            }

            return null;

        }

函数首先判断节点(就是一个DropDownItem)是否含有子节点,如果它不含有子节点就return它(这就是结束条件判断)。我们这样做完全是因为我们菜单使用习惯(所有的菜单功能都是在叶子节点实现功能的),当然我们也可以将非叶子节点也return回去。但是最好不要这么干,因为它会令我们产生很多困扰(不信邪的朋友可以试试)。下一步再分别遍历该节点的每一个子树

上面是遍历某个DropDownItem和它的子节点,下面遍历整个菜单栏:

…… 

                //这是遍历菜单栏,可以放在任何你需要的地方,

                //注: menuStrip1是我菜单栏的名字

                foreach (ToolStripMenuItem mItem in this.menuStrip1.Items)

                {    //递归遍历各个DropDownItem

                    Items(mItem);

                }

                //

……

上面就是遍历菜单的全部代码。这当然还没完,我们需要将遍历菜单得到的各个菜单项存入容器,以备下面的程序使用。什么容器都可以,而我选择了List<>。要实现这个功能:

首先,我们需要增加一个容器 lMenuItems

……

//增加一个全局变量,它是一个容器

List<ToolStripMenuItem> lMenuItems;

…… 

然后,在遍历菜单栏程序段中添加代码

                //这是遍历菜单栏,可以放在任何你需要的地方,

                //menuStrip1是我菜单栏的名字

                lMenuItems = new List<ToolStripMenuItem>();

                foreach (ToolStripMenuItem mItem in this.menuStrip1.Items)

                {    //递归遍历各个DropDownItem

                    Items(mItem);

                }

                //

……

         DropDownItem的递归遍历函数修改成下面这个样子

        private ToolStripMenuItem Items(ToolStripMenuItem tsItem)

        {    //结束条件判定

            if (tsItem.DropDownItems.Count <= 0) return tsItem;

            else

            {    //遍历各子树

                ToolStripMenuItem value = null;//临时变量

                foreach (ToolStripMenuItem mItem in tsItem.DropDownItems)

                {    //递归遍历mItem子树

                    value = Items(mItem);

                    if (value != null && lMenuItems != null)

                            lMenuItems.Add(value);

                }

            }

            return null;

        }

好,初战告捷。跳过如何提供用户的选择界面部分不提,直接进入重点。

 

二、  为工具栏动态添Items及其事件

给工具栏动态添加Items其实是一件非常简单的事,就像有些人说的new一个,再Add()进去就搞定了。关键的问题不在这里,如何使各个工具栏的Item的事件可以与DropDownItem的事件一一对应才是问题的关键。各个DropDownItem都可以拥有自己的事件,各个事件的名称不同,而且事件是不能直接拿事件赋值的,如果无法实现事件的动态赋值,菜单栏动态添加也就没戏了。如果没有好多解决方法,程序开发到这里只能是僵局。

 

1.   关于事件的调整

首先事件是可以调用事件的,并且几个控件可以共用一个事件。这就为问题的解决提供了可能性。让所有的可用菜单项都使用一个事件,或者说让这个事件统领其他的菜单事件。我们新建一个事件,并将这个事件命名为Menu_Click,它来统领整个Menu的所有Click事件

        private void Menu_Click(object sender, EventArgs e)

        { …… }

第二步,将原来所有DropDownItems的事件(菜单项事件)都替换成Menu_Click

小知识: 事件参数中的sender事实上就是发出事件的控件(或源),但因为它的类型是object,所有在使用前要对其进行强制类型转换。比如:有一个sender的实际类型是ToolStripItem,我需要获得senderName属性值就需要:

string sender_Name = ((ToolStripItem)sender).Name;

应用上面特点,在事件处理函数Menu_Click中就不难使用switch或者if/else来区分事件的来源,并分别调用他们自己的事件处理函数了。

2.   动态添加

解决了事件的问题,工具栏的动态添加实际上就是一句话的事

        toolStrip1.Items.Add(new ToolStripButton(

                                     <DropDownItem>.Text, //DropDownItem显示的文字

                                     <DropDownItem>.Image, //DropDownItem图标

                                     new System.EventHandler(Menu_Click), //DropDownItem事件

                                     <DropDownItem>.Name //DropDownItem名称

));

下面是一个简单的实例:(请将代码粘贴到你新建项目中对应得位置)

/*******************/

/*Form1.Designer.cs*/

/*******************/

namespace dynamicToolbar

{

    partial class Form1

    {

        /// <summary>

        /// Required designer variable.

        /// </summary>

        private System.ComponentModel.IContainer components = null;

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值