前面的話
在上一篇自己動手寫工具----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,迎娶白富美,走向人生巔峰
作者:悠揚的牧笛
博客地址:http://www.cnblogs.com/xhb-bky-blog/p/4167108.html
聲明:本博客原創文字只代表本人工作中在某一時間內總結的觀點或結論,與本人所在單位沒有直接利益關系。非商業,未授權貼子請以現狀保留,轉載時必須保留此段聲明,且在文章頁面明顯位置給出原文連接。