【原创】自己动手写工具----XSmartNote [Beta 2.0]

前面的话

在上一篇自己动手写工具----XSmartNote中,我简单介绍了这个小玩意儿的大致界面和要实现的功能,看了一下园子里的评论,评价褒贬不一,有人说“现在那么多云笔记的工具”,“极简版evernote”,我想说的是,别人的工具再好用,终究不是自己写的,其实写这个的目的,一方面是锻炼自己的技术能力,在coding的时候,或多或少会遇到一些问题,在解决这些问题的过程中,技术能力就会有所提升;另一方面,写这个东西还有自己个人原因,可以随时记录一些繁杂的知识点,通过给这些知识点打上标签,可以实现归类,那有的人会说,EverNote呢?嗯,如果你用着自己写的软件和用EverNote,哪个会更有成就感呢?好了,不多说,上图上代码!!

这个小东西基本上实现了上一篇中列出的功能,添加note、note分类、为note加标签、根据标签对note进行筛选等。下面介绍各个功能点

功能

添加note

首先在界面的右上角会提示您目前选择的树结构节点,如果新添加note就必须选择该note的所属目录(左侧的树节点),否则会因为找不到所属目录而导致添加note失败,如下图:

这样,新增的note就会自动归类为DOT NET文件夹下咯~

 1 private void btn_Save_Click(object sender, EventArgs e)
 2  {
 3      TreeNode node = tv_Folder.SelectedNode;
 4      TipsForm tf = new TipsForm();
 5      if (node == null)
 6      {
 7          return;
 8      }
 9      if (node.Tag.ToString() == Enums.LEAVES.ToString())
10      {
11          //同时更新标题和内容
12          int i = SQLHelper.UpdateContent(node.Name.ToInt(), txt_Title.Text, txt_Content.Text);
13          //同时重新加载Treeview
14          BuildTree(this.tv_Folder, GetFolderSet());
15          if (i > 0)
16          {
17              tf.Show("保存成功!");
18          }
19      }
20  }

由于建立新note时,note的ID就确定了,所以只要根据ID来更新几个字段就可以了。所以上面是更新操作而不是插入操作。

1  //更新标题及内容
2  public static int UpdateContent(int id,string title,string content)
3  {
4      int result = -1;
5      StringBuilder cmd = new StringBuilder();
6      cmd.Append(string.Format("update Table_Content set Content = '{0}',Title='{1}'  where Id={2}",content,title,id));
7      return NonQuery(cmd, result);
8  }

为note分类

这个比较简单了,只要在添加的时候指定好note的所属目录就可以了,单击目录时,右侧下方的预览区会显示出该目录下的所有note,并且最上方的标签区域显示该目录下所有的note包含的标签~

为note指定标签

为note指定标签的过程实际上是向关联note和标签的表中加入数据的过程,这里note和标签是多对多的关系,所以需要单独建立一个关系表。

为note加标签,是通过自定义控件LabelWithCheck的选中事件触发的,而且LabelWithCheck是在初始化时动态生成并且动态绑定事件的。

 1  public void AddLabelToLocation(FlowLayoutPanel flp, int column, string tag, int Id, bool ischecked,bool registerEvent)
 2  {
 3      //int flag = 0;
 4      int labelCount = flp.Controls.Count;
 5      int lines = labelCount / column;
 6      int left = labelCount % column;
 7      int X = (left * WIDTH) + (left + 1) * MARGIN;
 8      int Y = lines * HEIGHT + (lines + 1) * MARGIN;
 9      LabelWithCheck label = new LabelWithCheck();
10      //注册事件
11      if (registerEvent)
12      {
13          label.LabelCheckedEvent += Label_LabelCheckedEvent;
14          //new TipsForm().Show("注册插入数据库事件");
15      }
16      else
17      {
18          label.LabelCheckedEvent += Label_LabelSelectEvent;
19          //new TipsForm().Show("注册过滤事件");
20      }
21     
22      label.BackColor = ColorTranslator.FromHtml(ColorManager.ColorConvertor(flagForPanelEdit));
23      label.Location = new Point(X, Y);
24      label.LabelText = tag;//存储标签名称
25      label.Id = Id;//存储标签ID
26      label.LabelChecked = ischecked;//选中状态
27      flp.Controls.Add(label);
28      flagForPanelEdit++;
29      if (flagForPanelEdit > 19)
30      {
31          flagForPanelEdit = 0;
32      }
33  }

下面是自定义控件LabelWithCheck的代码,重绘LabelWithCheck

 1  #region OVERRIDE
 2  protected override void OnPaint(PaintEventArgs e)
 3  {
 4      Graphics g = e.Graphics;
 5      int x = this.Width;
 6      int y = this.Height;
 7      Point leftTop = new Point(0, 0);
 8      Point rightTop = new Point(x - 1, 0);
 9      Point leftBottom = new Point(0, y - 1);
10      Point rightBottom = new Point(x - 1, y - 1);
11 
12      g.DrawLine(new Pen(Color.White), leftTop, rightTop);
13      g.DrawLine(new Pen(Color.White), leftBottom, rightBottom);
14      g.DrawLine(new Pen(Color.White), leftTop, leftBottom);
15      g.DrawLine(new Pen(Color.White), rightTop, rightBottom);
16      //画上边缘
17      for (int i = 0; i < x - 1; i += 3)
18      {
19          g.FillRectangle(new SolidBrush(Color.Black), new Rectangle(i, 0, 2, 1));
20      }
21 
22      //画下边缘
23      for (int m = 0; m < x - 1; m += 3)
24      {
25          g.FillRectangle(new SolidBrush(Color.Black), new Rectangle(m, y - 1, 2, 1));
26      }
27 
28      //画左边缘
29      for (int i = 0; i < y - 1; i += 3)
30      {
31          g.FillRectangle(new SolidBrush(Color.Black), new Rectangle(0, i, 1, 2));
32      }
33 
34      //画右边缘
35      for (int i = 0; i < y - 1; i += 3)
36      {
37          g.FillRectangle(new SolidBrush(Color.Black), new Rectangle(x - 1, i, 1, 2));
38      }
39      base.OnPaint(e);
40  }
41  #endregion

定义LabelWithCheck控件的事件,为note添加标签的时候就触发这个事件,参数中包括了标签的一些信息

 1 #region EVENT
 2 public delegate void LabelWithCheckSelectedHandler(object sender, LabelWithCheckEventArgs e);
 3 public event LabelWithCheckSelectedHandler LabelCheckedEvent;
 4 private void ck_CheckedChanged(object sender, EventArgs e)//checkBox原型
 5 {
 6     if (LabelCheckedEvent != null)
 7     {
 8         LabelCheckedEvent(sender, new LabelWithCheckEventArgs(this._Id,this.LabelText));
 9     }
10 }
11 #endregion

 每选择一个LabelWithCheck都会动态添加该控件

1  private void Label_LabelSelectEvent(object sender, LabelWithCheckEventArgs e)
2  {
3      AddLabelToLocation(flowLayoutPanel2,6,e.LabelText,e.Id,false,false); //Stack Overflow 重复绑定重复执行 形成无限循环导致
4  }

根据目录和标签筛选

这一部分还没有仔细地去做,目前只是大概地处理了一下,最近实在太忙了。大概的筛选原则就是右侧上方的两个标签区域的交集,只要符合条件就会在下面的预览区域显示出来,也就是我们想要看到的结果啦~

上面一排是所选的目录下所有note包含的所有的标签,下面是手工指定的标签,通过筛选条件的就会出现在下面的note预览区域中

结语

本来这个小东西早就该完成,但是中间公司又分配了些项目,没有太多的空闲时间,今天抽空把他总结出来,对自己也有个交代。在写这个玩意儿的时候,的确遇到了一些小问题,如左侧树状结构绑定同一张表中带有层级结构的数据,这是第一次接触,但是掌握了方法就OK了;还有自定义控件的动态添加和绑定事件等等。如果您有什么建议,欢迎评论,大神勿拍... ...如果觉得好玩儿,就给个赞吧~~

2014马上过去了,不得不说时间飞快,祝各位园友在新的一年里,能够实现升职加薪,出任CTO,迎娶白富美,走向人生巅峰 

posted @ 2014-12-16 17:16  悠扬的牧笛  阅读(2001)  评论(10编辑  收藏  举报