(八十一)c#Winform自定义控件-时间轴
程序员文章站
2023-11-13 11:56:34
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:https://gitee.com/kwwwvagaa/net_winform_custom_contr ......
前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
github:https://github.com/kwwwvagaa/netwinformcontrol
码云:
如果觉得写的还行,请点个 star 支持一下吧
欢迎前来交流探讨: 企鹅群568015492
来都来了,点个【推荐】再走吧,谢谢
nuget
install-package hzh_controls
目录
用处及效果
准备工作
没什么可准备的,直接开干吧。
思路:
2个panel,分别放标题和明细
然后重绘控件,在标题旁边画圆并且连线
开始
添加一个类来存放节点信息
1 public class timelineitem 2 { 3 /// <summary> 4 /// gets or sets the title. 5 /// </summary> 6 /// <value>the title.</value> 7 public string title { get; set; } 8 /// <summary> 9 /// gets or sets the details. 10 /// </summary> 11 /// <value>the details.</value> 12 public string details { get; set; } 13 }
添加一个用户控件uctimeline
添加一些属性
1 /// <summary> 2 /// the line color 3 /// </summary> 4 private color linecolor = textcolors.light; 5 6 /// <summary> 7 /// gets or sets the color of the line. 8 /// </summary> 9 /// <value>the color of the line.</value> 10 [description("连接线颜色"), category("自定义")] 11 public color linecolor 12 { 13 get { return linecolor; } 14 set 15 { 16 linecolor = value; 17 invalidate(); 18 } 19 } 20 /// <summary> 21 /// the title font 22 /// </summary> 23 private font titlefont = new font("微软雅黑", 14f); 24 25 /// <summary> 26 /// gets or sets the title font. 27 /// </summary> 28 /// <value>the title font.</value> 29 [description("标题字体"), category("自定义")] 30 public font titlefont 31 { 32 get { return titlefont; } 33 set 34 { 35 titlefont = value; 36 reloaditems(); 37 } 38 } 39 40 /// <summary> 41 /// the title forcolor 42 /// </summary> 43 private color titleforcolor = textcolors.moredark; 44 45 /// <summary> 46 /// gets or sets the title forcolor. 47 /// </summary> 48 /// <value>the title forcolor.</value> 49 [description("标题颜色"), category("自定义")] 50 public color titleforcolor 51 { 52 get { return titleforcolor; } 53 set 54 { 55 titleforcolor = value; 56 reloaditems(); 57 } 58 } 59 60 /// <summary> 61 /// the details font 62 /// </summary> 63 private font detailsfont = new font("微软雅黑", 10); 64 65 /// <summary> 66 /// gets or sets the details font. 67 /// </summary> 68 /// <value>the details font.</value> 69 [description("详情字体"), category("自定义")] 70 public font detailsfont 71 { 72 get { return detailsfont; } 73 set 74 { 75 detailsfont = value; 76 reloaditems(); 77 } 78 } 79 80 /// <summary> 81 /// the details forcolor 82 /// </summary> 83 private color detailsforcolor = textcolors.light; 84 85 /// <summary> 86 /// gets or sets the details forcolor. 87 /// </summary> 88 /// <value>the details forcolor.</value> 89 [description("详情颜色"), category("自定义")] 90 public color detailsforcolor 91 { 92 get { return detailsforcolor; } 93 set 94 { 95 detailsforcolor = value; 96 reloaditems(); 97 } 98 } 99 100 /// <summary> 101 /// the items 102 /// </summary> 103 timelineitem[] items; 104 105 /// <summary> 106 /// gets or sets the items. 107 /// </summary> 108 /// <value>the items.</value> 109 [description("项列表"), category("自定义")] 110 public timelineitem[] items 111 { 112 get { return items; } 113 set 114 { 115 items = value; 116 reloaditems(); 117 } 118 }
构造函数初始化一些东西
1 public uctimeline() 2 { 3 this.setstyle(controlstyles.allpaintinginwmpaint, true); 4 this.setstyle(controlstyles.doublebuffer, true); 5 this.setstyle(controlstyles.resizeredraw, true); 6 this.setstyle(controlstyles.selectable, true); 7 this.setstyle(controlstyles.supportstransparentbackcolor, true); 8 this.setstyle(controlstyles.userpaint, true); 9 initializecomponent(); 10 items = new timelineitem[0]; 11 if (controlhelper.isdesignmode()) 12 { 13 items = new timelineitem[4]; 14 for (int i = 0; i < 4; i++) 15 { 16 items[i] = new timelineitem() 17 { 18 title = datetime.now.addmonths(-1 * (3 - i)).tostring("yyyy年mm月"), 19 details = datetime.now.addmonths(-1 * (3 - i)).tostring("yyyy年mm月") + "发生了一件大事,咔嚓一声打了一个炸雷,咔嚓一声打了一个炸雷,咔嚓一声打了一个炸雷,咔嚓一声打了一个炸雷,咔嚓一声打了一个炸雷,咔嚓一声打了一个炸雷,咔嚓一声打了一个炸雷,咔嚓一声打了一个炸雷,咔嚓一声打了一个炸雷,然后王二麻子他爹王咔嚓出生了。" 20 }; 21 } 22 reloaditems(); 23 } 24 }
重新加载列表
1 private void reloaditems() 2 { 3 try 4 { 5 controlhelper.freezecontrol(this, true); 6 this.controls.clear(); 7 if (items != null) 8 { 9 foreach (var item in items) 10 { 11 flowlayoutpanel paneltitle = new flowlayoutpanel(); 12 paneltitle.dock = dockstyle.top; 13 paneltitle.autoscroll = false; 14 paneltitle.padding = new system.windows.forms.padding(5); 15 paneltitle.name = "title_" + guid.newguid().tostring(); 16 17 label lbltitle = new label(); 18 lbltitle.dock = dockstyle.top; 19 lbltitle.autosize = true; 20 lbltitle.font = titlefont; 21 lbltitle.forecolor = titleforcolor; 22 lbltitle.text = item.title; 23 lbltitle.sizechanged += item_sizechanged; 24 paneltitle.controls.add(lbltitle); 25 this.controls.add(paneltitle); 26 paneltitle.bringtofront(); 27 28 29 flowlayoutpanel paneldetails = new flowlayoutpanel(); 30 paneldetails.dock = dockstyle.top; 31 paneldetails.autoscroll = false; 32 paneldetails.padding = new system.windows.forms.padding(5); 33 paneldetails.name = "details_" + guid.newguid().tostring(); 34 label lbldetails = new label(); 35 lbldetails.autosize = true; 36 lbldetails.dock = dockstyle.top; 37 lbldetails.font = detailsfont; 38 lbldetails.forecolor = detailsforcolor; 39 lbldetails.text = item.details; 40 lbldetails.sizechanged += item_sizechanged; 41 paneldetails.controls.add(lbldetails); 42 this.controls.add(paneldetails); 43 paneldetails.bringtofront(); 44 45 } 46 } 47 } 48 finally 49 { 50 controlhelper.freezecontrol(this, false); 51 } 52 }
当文本大小改变时改变面板大小
1 void item_sizechanged(object sender, eventargs e) 2 { 3 label lbl = (label)sender; 4 lbl.parent.height = lbl.height + 10; 5 }
重绘来画圆和连线
1 protected override void onpaint(painteventargs e) 2 { 3 base.onpaint(e); 4 var g = e.graphics; 5 g.setgdihigh(); 6 var lst = this.controls.toarray().where(p => p.name.startswith("title_")).tolist(); 7 for (int i = 0; i < lst.count; i++) 8 { 9 //画圆 10 g.drawellipse(new pen(new solidbrush(linecolor)), new rectangle(7, lst[i].location.y + 10, 16, 16)); 11 //划线 12 if (i != lst.count - 1) 13 { 14 g.drawline(new pen(new solidbrush(linecolor)), new point(7 + 8, lst[i].location.y + 10 - 2), new point(7 + 8, lst[i + 1].location.y + 10 + 16 + 2)); 15 } 16 } 17 }
最后的话
如果你喜欢的话,请到 点个星星吧