从零开始系列,用C#做软件产品:私人日记(四)右键菜单

不知大家是否有注意到,我们的教程开进了两节,也实现了几个小功能,但是到现在为止,我们好像还没有写过一句代码。都说码农码农,码在哪里?

之所以没编码,是之前的功能都太简单了,根本不需要编码。从这篇教程起,就涉及到编码了,不过在开始编码之前,还有一项重要的准备工作需要介绍下,那就是命名。

这里给大家讲个典故:当年子路问孔子,老师,卫国老大要是让你写代码,你第一件事先搞啥?孔子说,一定要先搞好函数命名!开个玩笑:)

清晰合理的命名可以让代码易于阅读,便于回忆。

比如一名学生有5门成绩,如果你是用成绩1、成绩2来表示,可能在项目做完后的短时期内你还记得,成绩1代表数学,成绩2代表英语,但时间一长你肯定就模糊了,成绩1是数学还是语文?别人就更不可能理解了,只能通过调试才能知道具体的含义。如果每段代码都是如此,所有代码都是毫无意义的字母和数字,那维护成本就会非常高。我们都知道保护代码最有效的方式就是混淆,就是为了增加阅读的难度。上面的例子,直接命名为score_math、score_english就非常好理解,或者英文不好,用拼音代替也可以,cj_sx、cj_yy,只要能方便理解,无论过了多长时间,一看就知道什么有意思。有句话说得好,最好的文档就是代码。

介绍完命名的重要性,再来讲下如何在VS中给控件命名:

我们现在对上次的treeview1控件命名,因为后续开发中有可能我们还有其他的treeview控件,这个是类别treeview控件,我们就给它命名为tvCategory。当然你也可以根据自己的理解自行命名。

接着之前的工程,点击树控件,左侧的的属性窗口,Name一栏,显示为treeview1,这个就是控件的名字。

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

我们可以改成tvCategory就完成命名了。

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

在接下来的开发中,新建控件我会直接做好命名,命名方法我就不再说明了。

接下来我们继续上一篇教程,做实现树控件的操作。我们把剩余的任务复制过来,方便查阅:

210826-4、采用树形控件表示,可显示分类图标;

210826-5、空白区域右键可新建根目录;

210826-6、鼠标右键点击分类项,可弹出管理菜单(新建、修改、删除);操作后自动刷新,删除前提示确认;

210826-7、鼠标左键点击分类项,可查询该分类项中的内容;

先逐个任务分析一下:

210826-4中我们已经使用了树控件,但显示分类图标需要有具体内容项才行,210826-5就是新建项的,所以210826-5优先。210826-6中提到了右键弹出管理菜单,可以与210826-5使用共同的菜单,这两个任务可以一起实现。

那我们今天要做的内容就是210826-5、210826-6中的部分功能。

一、创建菜单

所谓菜单,就是针对某个事物给用户一堆的选项,不同的选项就执行不同的代码,干不同的事情。

在.net core的windows应用框架中,菜单也是控件的一种,被分成两种形式:

标准菜单 :对应控件名称为MenuStrip

比如VS最上面的这一条

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

MenuStrip就是菜单栏的意思,这个很好理解。

弹出菜单 :对应控件名称为ContextMenuStrip

比如Windows资源管理器中,在某个目录点右键

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

Context的英文直译是上下文、来龙去脉、背景、语境,ContextMenuStrip组合起来就是上下文菜单。说实话我英文很烂,真的搞不懂为啥用Context这个单词来组合,可能是汉语跟英语思维方式不同,汉语的话叫弹出菜单、关联菜单,我觉得都好理解些,但是可能感觉不能完全达意。总之感觉这个单词很玄幻,我确实真的有点解释不清楚。如果你也搞不大明白,就当成弹出菜单吧。

很明显,我们需要的是一个弹出菜单:ContextMenuStrip。把ContextMenuStrip从工具箱中拖放到界面中,我们直接给它命名为cmsCategory。把控件加到界面的方法在上一篇教程已经说过了,所有控件的方式都一样,这种以后不再唠叨直接过了。

细心的朋友应该注意到了,这个控件稍有不同的是,它没有出现在界面中,而是出现在了设计界面的下方。只有你点击它的时候,它才会出现在上方,供编辑使用。

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

我们根据任务计划,分别在菜单中输入:新建、修改、删除,3个菜单项。并且分别在各自的属性窗口中命名tsmiCategoryCreate、tsmiCategoryModify、tsmiCategoryDelete。

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

菜单界面我们就设置好了。下面来研究怎么让它弹出来。

二、右键弹出菜单

以前在用VC++6.0编程的时候,鼠标右键弹出菜单都还是需要自己处理的,首先需要截获鼠标右键的点击事件,然后读取菜单资源,在当前鼠标位置处把菜单显示出来,编码过程比较复杂。而如今使用这些标准控件容易多了,标准功能都已经封装好了。有多容易呢?

看下图

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

我们点tvCategory控件,属性窗口找到ContextMenuStript,右边下拉框点一下,就看到了我们刚刚设置好的菜单,选中它,然后运行程序,在树控件点鼠标右键,发现菜单已经可以弹出了。

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

不过这只是一个小小的进步,点击任何菜单项都没有任何反应。

三、菜单事件响应

让我们再次回到菜单,选择cmsCategory,选择新建菜单项,在属性窗口的上部有个小闪电的图标

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

,鼠标移上去会显示”事件”的字样,点下这个图标,切换到事件视图。

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

找到Click,然后双击后面空白的位置。这时你会发现,VS自动跳转到了Form1.cs文件中,然后定位到了一段代码:

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

红框内的代码就是VS自动为我们新增的事件响应代码。

上面的这些操作是什么意思呢?我来解释下:

每个控件包括菜单项都有很多事件可以被用户处理,现在我们想处理用户点击新建菜单项的事件,Click就代表用户点击事件,双击它以后,VS就自动生成了一个函数,名称和参数都为你处理好了,你只需要在这个函数内写上你要处理的代码就好了。

那到底是不是这样呢?我们来试验一下,在windows桌面应用最简单直观的方式就是调用消息框来显示信息,于是我们在函数内写下如下代码:

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

然后运行程序,鼠标右键->选择新建,结果弹出如下信息。

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

按此方法,我们依次完成修改、删除菜单项的代码。

在做删除的时候,我们注意到,210826-6中要求:先让用户确认后才能删除的。

这里如果没有特殊的要求,还是可以通过MessageBox.Show来完成,因为这个函数提供了很多选项,当我们输入MessageBox.Show后的第一个(后,会弹出用法提示,我们看到有多达21种方式来调用这个函数,具体每一个就不展开了,有兴趣的学员可以自行尝试。事实上,VS之所以成为宇宙第一代码编辑器,其中有一项就是通过智能提示减少程序员的大量输入。

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

这里我们选择一种可以提供给用户确认的方式,代码如下:

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

运行程序点删除

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

按是继续弹出删除信息,按否则不弹出删除信息,达到预期。

现在我们发现,空白区域点开菜单,新建是有效的是符合常理的,但是修改和删除的存在就不合理了,至少应该隐藏或不被选中吧?看,需求就是这样被细化的。

四、菜单状态响应

如果你仍然是上面的路径,去每个菜单项找响应的事件,恐怕很难如愿。这个事件被定义在了cmsCategory控件的Opening事件中,你可以理解为当cmsCategory显示之前要做哪些事情。知道了哪里触发的事件,编码就相对容易了。

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

仍然是双击空白处自动添加代码,然后根据逻辑判断,当树控件有选择项时,修改和删除的菜单项有效,当树控件没有选择项时,修改和删除菜单无效。代码如下:

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

运行效果如下:

从零开始系列,用C#做软件产品:私人日记(四)右键菜单

当然你也可以采用下面注释掉的语句,直接就不显示。

以上,基本完成了弹出菜单项的基本界面操作,由于我没有从数据库设计开始做,所以再往下的功能需要预先模拟一些数据,篇幅原因今天先写到这。

提前跟大家说明下,孩子马上要开学了,这几天事情比较多,下次更新时间可能会稍长。

另外希望大家多多参与关注、转发、评论,粉丝到1万我就能开专栏了,现在这种文章都没有分类,感觉很不方便。

------------------------------------------------------------

本教程已作为开源项目加入到Git,代码内容会随教程实时更新,大家有兴趣的话可以关注我,以获得最及时的更新。私信:私人日记 可以来获取Git的链接。

大家阅读过程中有哪些看不懂或未尽兴的地方,可以在评论区留言,我会先记下来在后续的教程中找机会再说。