前提

入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。

开源地址:

如果觉得写的还行,请点个 star 支持一下吧

欢迎前来交流探讨: 企鹅群568015492 

目录

准备工作

表格控件将拆分为2部分,1:行元素控件,2:列表控件

为了具有更好的扩展性,更加的open,使用接口对行元素进行约束,当行样式或功能不满足你的需求的时候,可以自定义一个行元素,实现接口控件,然后将类型指定给列表控件即可

表格控件用到了分页控件,如果你还没有对分页控件进行了解,请移步查看

(十二)c#winform自定义控件-分页控件

开始

定义一些辅助东西

1  public class datagridviewcellentity
2     {
3         public string title { get; set; }
4         public int width { get; set; }
5         public system.windows.forms.sizetype widthtype { get; set; }
6 
7     }
1     public class datagridvieweventargs : eventargs
2     {
3         public control cellcontrol { get; set; }
4         public int cellindex { get; set; }
5         public int rowindex { get; set; }
6 
7 
8     }
1     [serializable]
2     [comvisible(true)]
3     public delegate void datagridvieweventhandler(object sender, datagridvieweventargs e);
1   public class datagridviewcolumnentity
2     {
3         public string headtext { get; set; }
4         public int width { get; set; }
5         public system.windows.forms.sizetype widthtype { get; set; }
6         public string datafield { get; set; }
7         public func<object, string> format { get; set; }
8     }

定义行接口

 1  public interface idatagridviewrow
 2     {
 3         /// <summary>
 4         /// checkbox选中事件
 5         /// </summary>
 6         event datagridvieweventhandler checkboxchangeevent;
 7         /// <summary>
 8         /// 点击单元格事件
 9         /// </summary>
10         event datagridvieweventhandler cellclick;
11         /// <summary>
12         /// 数据源改变事件
13         /// </summary>
14         event datagridvieweventhandler sourcechanged;
15         /// <summary>
16         /// 列参数,用于创建列数和宽度
17         /// </summary>
18         list<datagridviewcolumnentity> columns { get; set; }
19         bool isshowcheckbox { get; set; }
20         /// <summary>
21         /// 是否选中
22         /// </summary>
23         bool ischecked { get; set; }
24 
25         /// <summary>
26         /// 数据源
27         /// </summary>
28         object datasource { get; set; }
29         /// <summary>
30         /// 添加单元格元素,仅做添加控件操作,不做数据绑定,数据绑定使用bindingcells
31         /// </summary>
32         void reloadcells();
33         /// <summary>
34         /// 绑定数据到cell
35         /// </summary>
36         /// <param name="intindex">cell下标</param>
37         /// <returns>返回true则表示已处理过,否则将进行默认绑定(通常只针对有text值的控件)</returns>
38         void bindingcelldata();
39         /// <summary>
40         /// 设置选中状态,通常为设置颜色即可
41         /// </summary>
42         /// <param name="blnselected">是否选中</param>
43         void setselect(bool blnselected);
44     }

创建行控件

添加一个用户控件,命名ucdatagridviewrow,实现接口idatagridviewrow

属性

 1   #region 属性
 2         public event datagridvieweventhandler checkboxchangeevent;
 3 
 4         public event datagridvieweventhandler cellclick;
 5 
 6         public event datagridvieweventhandler sourcechanged;
 7 
 8         public list<datagridviewcolumnentity> columns
 9         {
10             get;
11             set;
12         }
13 
14         public object datasource
15         {
16             get;
17             set;
18         }
19 
20         public bool isshowcheckbox
21         {
22             get;
23             set;
24         }
25         private bool m_ischecked;
26         public bool ischecked
27         {
28             get
29             {
30                 return m_ischecked;
31             }
32 
33             set
34             {
35                 if (m_ischecked != value)
36                 {
37                     m_ischecked = value;
38                     (this.pancells.controls.find("check", false)[0] as uccheckbox).checked = value;
39                 }
40             }
41         }
42 
43 
44         #endregion

实现接口

  1    public void bindingcelldata()
  2         {
  3             for (int i = 0; i < columns.count; i++)
  4             {
  5                 datagridviewcolumnentity com = columns[i];
  6                 var cs = this.pancells.controls.find("lbl_" + com.datafield, false);
  7                 if (cs != null && cs.length > 0)
  8                 {
  9                     var pro = datasource.gettype().getproperty(com.datafield);
 10                     if (pro != null)
 11                     {
 12                         var value = pro.getvalue(datasource, null);
 13                         if (com.format != null)
 14                         {
 15                             cs[0].text = com.format(value);
 16                         }
 17                         else
 18                         {
 19                             cs[0].text = value.tostringext();
 20                         }
 21                     }
 22                 }
 23             }
 24         }
 25 
 26  public void setselect(bool blnselected)
 27         {
 28             if (blnselected)
 29             {
 30                 this.backcolor = color.fromargb(255, 247, 245);
 31             }
 32             else
 33             {
 34                 this.backcolor = color.transparent;
 35             }
 36         }
 37 
 38         public void reloadcells()
 39         {
 40             try
 41             {
 42                 controlhelper.freezecontrol(this, true);
 43                 this.pancells.controls.clear();
 44                 this.pancells.columnstyles.clear();
 45 
 46                 int intcolumnscount = columns.count();
 47                 if (columns != null && intcolumnscount > 0)
 48                 {
 49                     if (isshowcheckbox)
 50                     {
 51                         intcolumnscount++;
 52                     }
 53                     this.pancells.columncount = intcolumnscount;
 54                     for (int i = 0; i < intcolumnscount; i++)
 55                     {
 56                         control c = null;
 57                         if (i == 0 && isshowcheckbox)
 58                         {
 59                             this.pancells.columnstyles.add(new system.windows.forms.columnstyle(sizetype.absolute, 30f));
 60 
 61                             uccheckbox box = new uccheckbox();
 62                             box.name = "check";
 63                             box.textvalue = "";
 64                             box.size = new size(30, 30);
 65                             box.dock = dockstyle.fill;
 66                             box.checkedchangeevent += (a, b) =>
 67                             {
 68                                 ischecked = box.checked;
 69                                 if (checkboxchangeevent != null)
 70                                 {
 71                                     checkboxchangeevent(a, new datagridvieweventargs()
 72                                     {
 73                                         cellcontrol = box,
 74                                         cellindex = 0
 75                                     });
 76                                 }
 77                             };
 78                             c = box;
 79                         }
 80                         else
 81                         {
 82                             var item = columns[i - (isshowcheckbox ? 1 : 0)];
 83                             this.pancells.columnstyles.add(new system.windows.forms.columnstyle(item.widthtype, item.width));
 84 
 85                             label lbl = new label();
 86                             lbl.tag = i - (isshowcheckbox ? 1 : 0);
 87                             lbl.name = "lbl_" + item.datafield;
 88                             lbl.font = new font("微软雅黑", 12);
 89                             lbl.forecolor = color.black;
 90                             lbl.autosize = false;
 91                             lbl.dock = dockstyle.fill;
 92                             lbl.textalign = contentalignment.middlecenter;
 93                             lbl.mousedown += (a, b) =>
 94                             {
 95                                 item_mousedown(a, b);
 96                             };
 97                             c = lbl;
 98                         }
 99                         this.pancells.controls.add(c, i, 0);
100                     }
101 
102                 }
103             }
104             finally
105             {
106                 controlhelper.freezecontrol(this, false);
107             }
108         }

节点选中事件

 1    void item_mousedown(object sender, mouseeventargs e)
 2         {
 3             if (cellclick != null)
 4             {
 5                 cellclick(sender, new datagridvieweventargs()
 6                 {
 7                     cellcontrol = this,
 8                     cellindex = (sender as control).tag.toint()
 9                 });
10             }
11         }

完整的代码

  1 // 版权所有  黄正辉  交流群:568015492   qq:623128629
  2 // 文件名称:ucdatagridviewrow.cs
  3 // 创建日期:2019-08-15 15:59:31
  4 // 功能描述:datagridview
  5 // 项目地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
  6 using system;
  7 using system.collections.generic;
  8 using system.componentmodel;
  9 using system.drawing;
 10 using system.data;
 11 using system.linq;
 12 using system.text;
 13 using system.windows.forms;
 14 
 15 namespace hzh_controls.controls
 16 {
 17     [toolboxitem(false)]
 18     public partial class ucdatagridviewrow : usercontrol, idatagridviewrow
 19     {
 20 
 21         #region 属性
 22         public event datagridvieweventhandler checkboxchangeevent;
 23 
 24         public event datagridvieweventhandler cellclick;
 25 
 26         public event datagridvieweventhandler sourcechanged;
 27 
 28         public list<datagridviewcolumnentity> columns
 29         {
 30             get;
 31             set;
 32         }
 33 
 34         public object datasource
 35         {
 36             get;
 37             set;
 38         }
 39 
 40         public bool isshowcheckbox
 41         {
 42             get;
 43             set;
 44         }
 45         private bool m_ischecked;
 46         public bool ischecked
 47         {
 48             get
 49             {
 50                 return m_ischecked;
 51             }
 52 
 53             set
 54             {
 55                 if (m_ischecked != value)
 56                 {
 57                     m_ischecked = value;
 58                     (this.pancells.controls.find("check", false)[0] as uccheckbox).checked = value;
 59                 }
 60             }
 61         }
 62 
 63 
 64         #endregion
 65 
 66         public ucdatagridviewrow()
 67         {
 68             initializecomponent();
 69         }
 70 
 71         public void bindingcelldata()
 72         {
 73             for (int i = 0; i < columns.count; i++)
 74             {
 75                 datagridviewcolumnentity com = columns[i];
 76                 var cs = this.pancells.controls.find("lbl_" + com.datafield, false);
 77                 if (cs != null && cs.length > 0)
 78                 {
 79                     var pro = datasource.gettype().getproperty(com.datafield);
 80                     if (pro != null)
 81                     {
 82                         var value = pro.getvalue(datasource, null);
 83                         if (com.format != null)
 84                         {
 85                             cs[0].text = com.format(value);
 86                         }
 87                         else
 88                         {
 89                             cs[0].text = value.tostringext();
 90                         }
 91                     }
 92                 }
 93             }
 94         }
 95 
 96         void item_mousedown(object sender, mouseeventargs e)
 97         {
 98             if (cellclick != null)
 99             {
100                 cellclick(sender, new datagridvieweventargs()
101                 {
102                     cellcontrol = this,
103                     cellindex = (sender as control).tag.toint()
104                 });
105             }
106         }
107 
108         public void setselect(bool blnselected)
109         {
110             if (blnselected)
111             {
112                 this.backcolor = color.fromargb(255, 247, 245);
113             }
114             else
115             {
116                 this.backcolor = color.transparent;
117             }
118         }
119 
120         public void reloadcells()
121         {
122             try
123             {
124                 controlhelper.freezecontrol(this, true);
125                 this.pancells.controls.clear();
126                 this.pancells.columnstyles.clear();
127 
128                 int intcolumnscount = columns.count();
129                 if (columns != null && intcolumnscount > 0)
130                 {
131                     if (isshowcheckbox)
132                     {
133                         intcolumnscount++;
134                     }
135                     this.pancells.columncount = intcolumnscount;
136                     for (int i = 0; i < intcolumnscount; i++)
137                     {
138                         control c = null;
139                         if (i == 0 && isshowcheckbox)
140                         {
141                             this.pancells.columnstyles.add(new system.windows.forms.columnstyle(sizetype.absolute, 30f));
142 
143                             uccheckbox box = new uccheckbox();
144                             box.name = "check";
145                             box.textvalue = "";
146                             box.size = new size(30, 30);
147                             box.dock = dockstyle.fill;
148                             box.checkedchangeevent += (a, b) =>
149                             {
150                                 ischecked = box.checked;
151                                 if (checkboxchangeevent != null)
152                                 {
153                                     checkboxchangeevent(a, new datagridvieweventargs()
154                                     {
155                                         cellcontrol = box,
156                                         cellindex = 0
157                                     });
158                                 }
159                             };
160                             c = box;
161                         }
162                         else
163                         {
164                             var item = columns[i - (isshowcheckbox ? 1 : 0)];
165                             this.pancells.columnstyles.add(new system.windows.forms.columnstyle(item.widthtype, item.width));
166 
167                             label lbl = new label();
168                             lbl.tag = i - (isshowcheckbox ? 1 : 0);
169                             lbl.name = "lbl_" + item.datafield;
170                             lbl.font = new font("微软雅黑", 12);
171                             lbl.forecolor = color.black;
172                             lbl.autosize = false;
173                             lbl.dock = dockstyle.fill;
174                             lbl.textalign = contentalignment.middlecenter;
175                             lbl.mousedown += (a, b) =>
176                             {
177                                 item_mousedown(a, b);
178                             };
179                             c = lbl;
180                         }
181                         this.pancells.controls.add(c, i, 0);
182                     }
183 
184                 }
185             }
186             finally
187             {
188                 controlhelper.freezecontrol(this, false);
189             }
190         }
191 
192 
193     }
194 }
 1 namespace hzh_controls.controls
 2 {
 3     partial class ucdatagridviewrow
 4     {
 5         /// <summary> 
 6         /// 必需的设计器变量。
 7         /// </summary>
 8         private system.componentmodel.icontainer components = null;
 9 
10         /// <summary> 
11         /// 清理所有正在使用的资源。
12         /// </summary>
13         /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
14         protected override void dispose(bool disposing)
15         {
16             if (disposing && (components != null))
17             {
18                 components.dispose();
19             }
20             base.dispose(disposing);
21         }
22 
23         #region 组件设计器生成的代码
24 
25         /// <summary> 
26         /// 设计器支持所需的方法 - 不要
27         /// 使用代码编辑器修改此方法的内容。
28         /// </summary>
29         private void initializecomponent()
30         {
31             this.ucsplitline_h1 = new hzh_controls.controls.ucsplitline_h();
32             this.pancells = new system.windows.forms.tablelayoutpanel();
33             this.suspendlayout();
34             // 
35             // ucsplitline_h1
36             // 
37             this.ucsplitline_h1.backcolor = system.drawing.color.fromargb(((int)(((byte)(232)))), ((int)(((byte)(232)))), ((int)(((byte)(232)))));
38             this.ucsplitline_h1.dock = system.windows.forms.dockstyle.bottom;
39             this.ucsplitline_h1.location = new system.drawing.point(0, 55);
40             this.ucsplitline_h1.name = "ucsplitline_h1";
41             this.ucsplitline_h1.size = new system.drawing.size(661, 1);
42             this.ucsplitline_h1.tabindex = 0;
43             this.ucsplitline_h1.tabstop = false;
44             // 
45             // pancells
46             // 
47             this.pancells.columncount = 1;
48             this.pancells.columnstyles.add(new system.windows.forms.columnstyle(system.windows.forms.sizetype.percent, 100f));
49             this.pancells.columnstyles.add(new system.windows.forms.columnstyle(system.windows.forms.sizetype.absolute, 20f));
50             this.pancells.dock = system.windows.forms.dockstyle.fill;
51             this.pancells.location = new system.drawing.point(0, 0);
52             this.pancells.name = "pancells";
53             this.pancells.rowcount = 1;
54             this.pancells.rowstyles.add(new system.windows.forms.rowstyle(system.windows.forms.sizetype.percent, 100f));
55             this.pancells.rowstyles.add(new system.windows.forms.rowstyle(system.windows.forms.sizetype.absolute, 20f));
56             this.pancells.size = new system.drawing.size(661, 55);
57             this.pancells.tabindex = 1;
58             // 
59             // ucdatagridviewitem
60             // 
61             this.autoscalemode = system.windows.forms.autoscalemode.none;
62             this.backcolor = system.drawing.color.white;
63             this.controls.add(this.pancells);
64             this.controls.add(this.ucsplitline_h1);
65             this.name = "ucdatagridviewitem";
66             this.size = new system.drawing.size(661, 56);
67             this.resumelayout(false);
68 
69         }
70 
71         #endregion
72 
73         private ucsplitline_h ucsplitline_h1;
74         private system.windows.forms.tablelayoutpanel pancells;
75     }
76 }

 

接下来就是列表控件了

添加一个用户控件,命名ucdatagridview

属性

  1  #region 属性
2         private font m_headfont = new font("微软雅黑", 12f);
3         /// <summary>
4         /// 标题字体
5         /// </summary>
6         [description("标题字体"), category("自定义")]
7         public font headfont
8         {
9             get { return m_headfont; }
10             set { m_headfont = value; }
11         }
12         private color m_headtextcolor = color.black;
13         /// <summary>
14         /// 标题字体颜色
15         /// </summary>
16         [description("标题文字颜色"), category("自定义")]
17         public color headtextcolor
18         {
19             get { return m_headtextcolor; }
20             set { m_headtextcolor = value; }
21         }
22 
23         private bool m_isshowhead = true;
24         /// <summary>
25         /// 是否显示标题
26         /// </summary>
27         [description("是否显示标题"), category("自定义")]
28         public bool isshowhead
29         {
30             get { return m_isshowhead; }
31             set
32             {
33                 m_isshowhead = value;
34                 panhead.visible = value;
35                 if (m_page != null)
36                 {
37                     resetshowcount();
38                     m_page.pagesize = m_showcount;
39                 }
40             }
41         }
42         private int m_headheight = 40;
43         /// <summary>
44         /// 标题高度
45         /// </summary>
46         [description("标题高度"), category("自定义")]
47         public int headheight
48         {
49             get { return m_headheight; }
50             set
51             {
52                 m_headheight = value;
53                 panhead.height = value;
54             }
55         }
56 
57         private bool m_isshowcheckbox = false;
58         /// <summary>
59         /// 是否显示复选框
60         /// </summary>
61         [description("是否显示选择框"), category("自定义")]
62         public bool isshowcheckbox
63         {
64             get { return m_isshowcheckbox; }
65             set
66             {
67                 if (value != m_isshowcheckbox)
68                 {
69                     m_isshowcheckbox = value;
70                     loadcolumns();
71                 }
72             }
73         }
74 
75         private int m_rowheight = 40;
76         /// <summary>
77         /// 行高
78         /// </summary>
79         [description("数据行高"), category("自定义")]
80         public int rowheight
81         {
82             get { return m_rowheight; }
83             set { m_rowheight = value; }
84         }
85 
86         private int m_showcount = 0;
87         /// <summary>
88         /// 
89         /// </summary>
90         [description("可显示个数"), category("自定义")]
91         public int showcount
92         {
93             get { return m_showcount; }
94             private set
95             {
96                 m_showcount = value;
97                 if (m_page != null)
98                 {
99                     m_page.pagesize = value;
100                 }
101             }
102         }
103 
104         private list<datagridviewcolumnentity> m_columns;
105         /// <summary>
106         /// 列
107         /// </summary>
108         [description("列"), category("自定义")]
109         public list<datagridviewcolumnentity> columns
110         {
111             get { return m_columns; }
112             set
113             {
114                 m_columns = value;
115                 loadcolumns();
116             }
117         }
118 
119         private object m_datasource;
120         /// <summary>
121         /// 数据源,支持列表或table,如果使用翻页控件,请使用翻页控件的datasource
122         /// </summary>
123         [description("数据源,支持列表或table,如果使用翻页控件,请使用翻页控件的datasource"), category("自定义")]
124         public object datasource
125         {
126             get { return m_datasource; }
127             set
128             {
129                 if (value == null)
130                     return;
131                 if (!(m_datasource is datatable) && (!typeof(ilist).isassignablefrom(value.gettype())))
132                 {
133                     throw new exception("数据源不是有效的数据类型,请使用datatable或列表");
134                 }
135 
136                 m_datasource = value;
137                 reloadsource();
138             }
139         }
140 
141         public list<idatagridviewrow> rows { get; private set; }
142 
143         private type m_rowtype = typeof(ucdatagridviewrow);
144         /// <summary>
145         /// 行元素类型,默认ucdatagridviewitem
146         /// </summary>
147         [description("行控件类型,默认ucdatagridviewrow,如果不满足请自定义行控件实现接口idatagridviewrow"), category("自定义")]
148         public type rowtype
149         {
150             get { return m_rowtype; }
151             set
152             {
153                 if (value == null)
154                     return;
155                 if (!typeof(idatagridviewrow).isassignablefrom(value) || !value.issubclassof(typeof(control)))
156                     throw new exception("行控件没有实现idatagridviewrow接口");
157                 m_rowtype = value;
158             }
159         }
160         idatagridviewrow m_selectrow = null;
161         /// <summary>
162         /// 选中的节点
163         /// </summary>
164         [description("选中行"), category("自定义")]
165         public idatagridviewrow selectrow
166         {
167             get { return m_selectrow; }
168             private set { m_selectrow = value; }
169         }
170 
171 
172         /// <summary>
173         /// 选中的行,如果显示checkbox,则以checkbox选中为准
174         /// </summary>
175         [description("选中的行,如果显示checkbox,则以checkbox选中为准"), category("自定义")]
176         public list<idatagridviewrow> selectrows
177         {
178             get
179             {
180                 if (m_isshowcheckbox)
181                 {
182                     return rows.findall(p => p.ischecked);
183                 }
184                 else
185                     return new list<idatagridviewrow>() { m_selectrow };
186             }
187         }
188 
189 
190         private ucpagercontrolbase m_page = null;
191         /// <summary>
192         /// 翻页控件
193         /// </summary>
194         [description("翻页控件,如果ucpagercontrol不满足你的需求,请自定义翻页控件并继承ucpagercontrolbase"), category("自定义")]
195         public ucpagercontrolbase page
196         {
197             get { return m_page; }
198             set
199             {
200                 m_page = value;
201                 if (value != null)
202                 {
203                     if (!typeof(ipagecontrol).isassignablefrom(value.gettype()) || !value.gettype().issubclassof(typeof(ucpagercontrolbase)))
204                         throw new exception("翻页控件没有继承ucpagercontrolbase");
205                     panpage.visible = value != null;
206                     m_page.showsourcechanged += page_showsourcechanged;
207                     m_page.dock = dockstyle.fill;
208                     this.panpage.controls.clear();
209                     this.panpage.controls.add(m_page);
210                     resetshowcount();
211                     m_page.pagesize = showcount;
212                     this.datasource = m_page.getcurrentsource();
213                 }
214                 else
215                 {
216                     m_page = null;
217                 }
218             }
219         }
220 
221         void page_showsourcechanged(object currentsource)
222         {
223             this.datasource = currentsource;
224         }
225 
226         #region 事件
227         [description("选中标题选择框事件"), category("自定义")]
228         public eventhandler headcheckboxchangeevent;
229         [description("标题点击事件"), category("自定义")]
230         public eventhandler headcolumnclickevent;
231         [description("项点击事件"), category("自定义")]
232         public event datagridvieweventhandler itemclick;
233         [description("数据源改变事件"), category("自定义")]
234         public event datagridvieweventhandler sourcechanged;
235         #endregion
236         #endregion

一些私有的方法

 1   #region 私有方法
2         #region 加载column
3         /// <summary>
4         /// 功能描述:加载column
5         /// 作  者:hzh
6         /// 创建日期:2019-08-08 17:51:50
7         /// 任务编号:pos
8         /// </summary>
9         private void loadcolumns()
10         {
11             try
12             {
13                 if (designmode)
14                 { return; }
15 
16                 controlhelper.freezecontrol(this.panhead, true);
17                 this.pancolumns.controls.clear();
18                 this.pancolumns.columnstyles.clear();
19 
20                 if (m_columns != null && m_columns.count() > 0)
21                 {
22                     int intcolumnscount = m_columns.count();
23                     if (m_isshowcheckbox)
24                     {
25                         intcolumnscount++;
26                     }
27                     this.pancolumns.columncount = intcolumnscount;
28                     for (int i = 0; i < intcolumnscount; i++)
29                     {
30                         control c = null;
31                         if (i == 0 && m_isshowcheckbox)
32                         {
33                             this.pancolumns.columnstyles.add(new system.windows.forms.columnstyle(sizetype.absolute, 30f));
34 
35                             uccheckbox box = new uccheckbox();
36                             box.textvalue = "";
37                             box.size = new size(30, 30);
38                             box.checkedchangeevent += (a, b) =>
39                             {
40                                 rows.foreach(p => p.ischecked = box.checked);
41                                 if (headcheckboxchangeevent != null)
42                                 {
43                                     headcheckboxchangeevent(a, b);
44                                 }
45                             };
46                             c = box;
47                         }
48                         else
49                         {
50                             var item = m_columns[i - (m_isshowcheckbox ? 1 : 0)];
51                             this.pancolumns.columnstyles.add(new system.windows.forms.columnstyle(item.widthtype, item.width));
52                             label lbl = new label();
53                             lbl.name = "dgvcolumns_" + i;
54                             lbl.text = item.headtext;
55                             lbl.font = m_headfont;
56                             lbl.forecolor = m_headtextcolor;
57                             lbl.textalign = contentalignment.middlecenter;
58                             lbl.autosize = false;
59                             lbl.dock = dockstyle.fill;
60                             lbl.mousedown += (a, b) =>
61                             {
62                                 if (headcolumnclickevent != null)
63                                 {
64                                     headcolumnclickevent(a, b);
65                                 }
66                             };
67                             c = lbl;
68                         }
69                         this.pancolumns.controls.add(c, i, 0);
70                     }
71 
72                 }
73             }
74             finally
75             {
76                 controlhelper.freezecontrol(this.panhead, false);
77             }
78         }
79         #endregion
80 
81         /// <summary>
82         /// 功能描述:获取显示个数
83         /// 作  者:hzh
84         /// 创建日期:2019-03-05 10:02:58
85         /// 任务编号:pos
86         /// </summary>
87         /// <returns>返回值</returns>
88         private void resetshowcount()
89         {
90             if (designmode)
91             { return; }
92             showcount = this.panrow.height / (m_rowheight);
93             int intcha = this.panrow.height % (m_rowheight);
94             m_rowheight += intcha / showcount;
95         }
96         #endregion

几个事件

 1  #region 事件
2         void rowsourcechanged(object sender, datagridvieweventargs e)
3         {
4             if (sourcechanged != null)
5                 sourcechanged(sender, e);
6         }
7         private void setselectrow(control item, datagridvieweventargs e)
8         {
9             try
10             {
11                 controlhelper.freezecontrol(this, true);
12                 if (item == null)
13                     return;
14                 if (item.visible == false)
15                     return;
16                 this.findform().activecontrol = this;
17                 this.findform().activecontrol = item;
18                 if (m_selectrow != null)
19                 {
20                     if (m_selectrow == item)
21                         return;
22                     m_selectrow.setselect(false);
23                 }
24                 m_selectrow = item as idatagridviewrow;
25                 m_selectrow.setselect(true);
26                 if (itemclick != null)
27                 {
28                     itemclick(item, e);
29                 }
30                 if (this.panrow.controls.count > 0)
31                 {
32                     if (item.location.y < 0)
33                     {
34                         this.panrow.autoscrollposition = new point(0, math.abs(this.panrow.controls[this.panrow.controls.count - 1].location.y) + item.location.y);
35                     }
36                     else if (item.location.y + m_rowheight > this.panrow.height)
37                     {
38                         this.panrow.autoscrollposition = new point(0, math.abs(this.panrow.autoscrollposition.y) + item.location.y - this.panrow.height + m_rowheight);
39                     }
40                 }
41             }
42             finally
43             {
44                 controlhelper.freezecontrol(this, false);
45             }
46         }
47         private void ucdatagridview_resize(object sender, eventargs e)
48         {
49             resetshowcount();
50             reloadsource();
51         }
52         #endregion

对外公开的函数

  1  #region 公共函数
2         /// <summary>
3         /// 刷新数据
4         /// </summary>
5         public void reloadsource()
6         {
7             if (designmode)
8             { return; }
9             try
10             {
11                 if (m_columns == null || m_columns.count <= 0)
12                     return;
13 
14                 controlhelper.freezecontrol(this.panrow, true);
15                 this.panrow.controls.clear();
16                 rows = new list<idatagridviewrow>();
17                 if (m_datasource != null)
18                 {
19                     int intindex = 0;
20                     control lastitem = null;
21 
22                     int intsourcecount = 0;
23                     if (m_datasource is datatable)
24                     {
25                         intsourcecount = (m_datasource as datatable).rows.count;
26                     }
27                     else if (typeof(ilist).isassignablefrom(m_datasource.gettype()))
28                     {
29                         intsourcecount = (m_datasource as ilist).count;
30                     }
31 
32                     foreach (control item in this.panrow.controls)
33                     {
34 
35 
36                         if (intindex >= intsourcecount)
37                         {
38                             item.visible = false;
39                         }
40                         else
41                         {
42                             var row = (item as idatagridviewrow);
43                             row.isshowcheckbox = m_isshowcheckbox;
44                             if (m_datasource is datatable)
45                             {
46                                 row.datasource = (m_datasource as datatable).rows[intindex];
47                             }
48                             else
49                             {
50                                 row.datasource = (m_datasource as ilist)[intindex];
51                             }
52                             row.bindingcelldata();
53                             item.height = m_rowheight;
54                             item.visible = true;
55                             item.bringtofront();
56                             if (lastitem == null)
57                                 lastitem = item;
58                             rows.add(row);
59                         }
60                         intindex++;
61                     }
62 
63                     if (intindex < intsourcecount)
64                     {
65                         for (int i = intindex; i < intsourcecount; i++)
66                         {
67                             idatagridviewrow row = (idatagridviewrow)activator.createinstance(m_rowtype);
68                             if (m_datasource is datatable)
69                             {
70                                 row.datasource = (m_datasource as datatable).rows[i];
71                             }
72                             else
73                             {
74                                 row.datasource = (m_datasource as ilist)[i];
75                             }
76                             row.columns = m_columns;
77                             list<control> lstcells = new list<control>();
78                             row.isshowcheckbox = m_isshowcheckbox;
79                             row.reloadcells();
80                             row.bindingcelldata();
81 
82 
83                             control rowcontrol = (row as control);
84                             rowcontrol.height = m_rowheight;
85                             this.panrow.controls.add(rowcontrol);
86                             rowcontrol.dock = dockstyle.top;
87                             row.cellclick += (a, b) => { setselectrow(rowcontrol, b); };
88                             row.checkboxchangeevent += (a, b) => { setselectrow(rowcontrol, b); };
89                             row.sourcechanged += rowsourcechanged;
90                             rowcontrol.bringtofront();
91                             rows.add(row);
92 
93                             if (lastitem == null)
94                                 lastitem = rowcontrol;
95                         }
96                     }
97                     if (lastitem != null && intsourcecount == m_showcount)
98                     {
99                         lastitem.height = this.panrow.height - (m_showcount - 1) * m_rowheight;
100                     }
101                 }
102             }
103             finally
104             {
105                 controlhelper.freezecontrol(this.panrow, false);
106             }
107         }
108 
109 
110         /// <summary>
111         /// 快捷键
112         /// </summary>
113         /// <param name="msg"></param>
114         /// <param name="keydata"></param>
115         /// <returns></returns>
116         protected override bool processcmdkey(ref message msg, keys keydata)
117         {
118             if (keydata == keys.up)
119             {
120                 previous();
121             }
122             else if (keydata == keys.down)
123             {
124                 next();
125             }
126             else if (keydata == keys.home)
127             {
128                 first();
129             }
130             else if (keydata == keys.end)
131             {
132                 end();
133             }
134             return base.processcmdkey(ref msg, keydata);
135         }
136         /// <summary>
137         /// 选中第一个
138         /// </summary>
139         public void first()
140         {
141             if (rows == null || rows.count <= 0)
142                 return;
143             control c = null;
144             c = (rows[0] as control);
145             setselectrow(c, new datagridvieweventargs() { rowindex = 0 });
146         }
147         /// <summary>
148         /// 选中上一个
149         /// </summary>
150         public void previous()
151         {
152             if (rows == null || rows.count <= 0)
153                 return;
154             control c = null;
155 
156             int index = rows.indexof(m_selectrow);
157             if (index - 1 >= 0)
158             {
159                 c = (rows[index - 1] as control);
160                 setselectrow(c, new datagridvieweventargs() { rowindex = index - 1 });
161             }
162         }
163         /// <summary>
164         /// 选中下一个
165         /// </summary>
166         public void next()
167         {
168             if (rows == null || rows.count <= 0)
169                 return;
170             control c = null;
171 
172             int index = rows.indexof(m_selectrow);
173             if (index + 1 < rows.count)
174             {
175                 c = (rows[index + 1] as control);
176                 setselectrow(c, new datagridvieweventargs() { rowindex = index + 1 });
177             }
178         }
179         /// <summary>
180         /// 选中最后一个
181         /// </summary>
182         public void end()
183         {
184             if (rows == null || rows.count <= 0)
185                 return;
186             control c = null;
187             c = (rows[rows.count - 1] as control);
188             setselectrow(c, new datagridvieweventargs() { rowindex = rows.count - 1 });
189         }
190 
191         #endregion

完整代码

  1 // 版权所有  黄正辉  交流群:568015492   qq:623128629
2 // 文件名称:ucdatagridview.cs
3 // 创建日期:2019-08-15 15:59:25
4 // 功能描述:datagridview
5 // 项目地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
6 using system;
7 using system.collections.generic;
8 using system.componentmodel;
9 using system.drawing;
10 using system.data;
11 using system.linq;
12 using system.text;
13 using system.windows.forms;
14 using system.collections;
15 
16 namespace hzh_controls.controls
17 {
18     public partial class ucdatagridview : usercontrol
19     {
20         #region 属性
21         private font m_headfont = new font("微软雅黑", 12f);
22         /// <summary>
23         /// 标题字体
24         /// </summary>
25         [description("标题字体"), category("自定义")]
26         public font headfont
27         {
28             get { return m_headfont; }
29             set { m_headfont = value; }
30         }
31         private color m_headtextcolor = color.black;
32         /// <summary>
33         /// 标题字体颜色
34         /// </summary>
35         [description("标题文字颜色"), category("自定义")]
36         public color headtextcolor
37         {
38             get { return m_headtextcolor; }
39             set { m_headtextcolor = value; }
40         }
41 
42         private bool m_isshowhead = true;
43         /// <summary>
44         /// 是否显示标题
45         /// </summary>
46         [description("是否显示标题"), category("自定义")]
47         public bool isshowhead
48         {
49             get { return m_isshowhead; }
50             set
51             {
52                 m_isshowhead = value;
53                 panhead.visible = value;
54                 if (m_page != null)
55                 {
56                     resetshowcount();
57                     m_page.pagesize = m_showcount;
58                 }
59             }
60         }
61         private int m_headheight = 40;
62         /// <summary>
63         /// 标题高度
64         /// </summary>
65         [description("标题高度"), category("自定义")]
66         public int headheight
67         {
68             get { return m_headheight; }
69             set
70             {
71                 m_headheight = value;
72                 panhead.height = value;
73             }
74         }
75 
76         private bool m_isshowcheckbox = false;
77         /// <summary>
78         /// 是否显示复选框
79         /// </summary>
80         [description("是否显示选择框"), category("自定义")]
81         public bool isshowcheckbox
82         {
83             get { return m_isshowcheckbox; }
84             set
85             {
86                 if (value != m_isshowcheckbox)
87                 {
88                     m_isshowcheckbox = value;
89                     loadcolumns();
90                 }
91             }
92         }
93 
94         private int m_rowheight = 40;
95         /// <summary>
96         /// 行高
97         /// </summary>
98         [description("数据行高"), category("自定义")]
99         public int rowheight
100         {
101             get { return m_rowheight; }
102             set { m_rowheight = value; }
103         }
104 
105         private int m_showcount = 0;
106         /// <summary>
107         /// 
108         /// </summary>
109         [description("可显示个数"), category("自定义")]
110         public int showcount
111         {
112             get { return m_showcount; }
113             private set
114             {
115                 m_showcount = value;
116                 if (m_page != null)
117                 {
118                     m_page.pagesize = value;
119                 }
120             }
121         }
122 
123         private list<datagridviewcolumnentity> m_columns;
124         /// <summary>
125         /// 列
126         /// </summary>
127         [description("列"), category("自定义")]
128         public list<datagridviewcolumnentity> columns
129         {
130             get { return m_columns; }
131             set
132             {
133                 m_columns = value;
134                 loadcolumns();
135             }
136         }
137 
138         private object m_datasource;
139         /// <summary>
140         /// 数据源,支持列表或table,如果使用翻页控件,请使用翻页控件的datasource
141         /// </summary>
142         [description("数据源,支持列表或table,如果使用翻页控件,请使用翻页控件的datasource"), category("自定义")]
143         public object datasource
144         {
145             get { return m_datasource; }
146             set
147             {
148                 if (value == null)
149                     return;
150                 if (!(m_datasource is datatable) && (!typeof(ilist).isassignablefrom(value.gettype())))
151                 {
152                     throw new exception("数据源不是有效的数据类型,请使用datatable或列表");
153                 }
154 
155                 m_datasource = value;
156                 reloadsource();
157             }
158         }
159 
160         public list<idatagridviewrow> rows { get; private set; }
161 
162         private type m_rowtype = typeof(ucdatagridviewrow);
163         /// <summary>
164         /// 行元素类型,默认ucdatagridviewitem
165         /// </summary>
166         [description("行控件类型,默认ucdatagridviewrow,如果不满足请自定义行控件实现接口idatagridviewrow"), category("自定义")]
167         public type rowtype
168         {
169             get { return m_rowtype; }
170             set
171             {
172                 if (value == null)
173                     return;
174                 if (!typeof(idatagridviewrow).isassignablefrom(value) || !value.issubclassof(typeof(control)))
175                     throw new exception("行控件没有实现idatagridviewrow接口");
176                 m_rowtype = value;
177             }
178         }
179         idatagridviewrow m_selectrow = null;
180         /// <summary>
181         /// 选中的节点
182         /// </summary>
183         [description("选中行"), category("自定义")]
184         public idatagridviewrow selectrow
185         {
186             get { return m_selectrow; }
187             private set { m_selectrow = value; }
188         }
189 
190 
191         /// <summary>
192         /// 选中的行,如果显示checkbox,则以checkbox选中为准
193         /// </summary>
194         [description("选中的行,如果显示checkbox,则以checkbox选中为准"), category("自定义")]
195         public list<idatagridviewrow> selectrows
196         {
197             get
198             {
199                 if (m_isshowcheckbox)
200                 {
201                     return rows.findall(p => p.ischecked);
202                 }
203                 else
204                     return new list<idatagridviewrow>() { m_selectrow };
205             }
206         }
207 
208 
209         private ucpagercontrolbase m_page = null;
210         /// <summary>
211         /// 翻页控件
212         /// </summary>
213         [description("翻页控件,如果ucpagercontrol不满足你的需求,请自定义翻页控件并继承ucpagercontrolbase"), category("自定义")]
214         public ucpagercontrolbase page
215         {
216             get { return m_page; }
217             set
218             {
219                 m_page = value;
220                 if (value != null)
221                 {
222                     if (!typeof(ipagecontrol).isassignablefrom(value.gettype()) || !value.gettype().issubclassof(typeof(ucpagercontrolbase)))
223                         throw new exception("翻页控件没有继承ucpagercontrolbase");
224                     panpage.visible = value != null;
225                     m_page.showsourcechanged += page_showsourcechanged;
226                     m_page.dock = dockstyle.fill;
227                     this.panpage.controls.clear();
228                     this.panpage.controls.add(m_page);
229                     resetshowcount();
230                     m_page.pagesize = showcount;
231                     this.datasource = m_page.getcurrentsource();
232                 }
233                 else
234                 {
235                     m_page = null;
236                 }
237             }
238         }
239 
240         void page_showsourcechanged(object currentsource)
241         {
242             this.datasource = currentsource;
243         }
244 
245         #region 事件
246         [description("选中标题选择框事件"), category("自定义")]
247         public eventhandler headcheckboxchangeevent;
248         [description("标题点击事件"), category("自定义")]
249         public eventhandler headcolumnclickevent;
250         [description("项点击事件"), category("自定义")]
251         public event datagridvieweventhandler itemclick;
252         [description("数据源改变事件"), category("自定义")]
253         public event datagridvieweventhandler sourcechanged;
254         #endregion
255         #endregion
256 
257         public ucdatagridview()
258         {
259             initializecomponent();
260         }
261 
262         #region 私有方法
263         #region 加载column
264         /// <summary>
265         /// 功能描述:加载column
266         /// 作  者:hzh
267         /// 创建日期:2019-08-08 17:51:50
268         /// 任务编号:pos
269         /// </summary>
270         private void loadcolumns()
271         {
272             try
273             {
274                 if (designmode)
275                 { return; }
276 
277                 controlhelper.freezecontrol(this.panhead, true);
278                 this.pancolumns.controls.clear();
279                 this.pancolumns.columnstyles.clear();
280 
281                 if (m_columns != null && m_columns.count() > 0)
282                 {
283                     int intcolumnscount = m_columns.count();
284                     if (m_isshowcheckbox)
285                     {
286                         intcolumnscount++;
287                     }
288                     this.pancolumns.columncount = intcolumnscount;
289                     for (int i = 0; i < intcolumnscount; i++)
290                     {
291                         control c = null;
292                         if (i == 0 && m_isshowcheckbox)
293                         {
294                             this.pancolumns.columnstyles.add(new system.windows.forms.columnstyle(sizetype.absolute, 30f));
295 
296                             uccheckbox box = new uccheckbox();
297                             box.textvalue = "";
298                             box.size = new size(30, 30);
299                             box.checkedchangeevent += (a, b) =>
300                             {
301                                 rows.foreach(p => p.ischecked = box.checked);
302                                 if (headcheckboxchangeevent != null)
303                                 {
304                                     headcheckboxchangeevent(a, b);
305                                 }
306                             };
307                             c = box;
308                         }
309                         else
310                         {
311                             var item = m_columns[i - (m_isshowcheckbox ? 1 : 0)];
312                             this.pancolumns.columnstyles.add(new system.windows.forms.columnstyle(item.widthtype, item.width));
313                             label lbl = new label();
314                             lbl.name = "dgvcolumns_" + i;
315                             lbl.text = item.headtext;
316                             lbl.font = m_headfont;
317                             lbl.forecolor = m_headtextcolor;
318                             lbl.textalign = contentalignment.middlecenter;
319                             lbl.autosize = false;
320                             lbl.dock = dockstyle.fill;
321                             lbl.mousedown += (a, b) =>
322                             {
323                                 if (headcolumnclickevent != null)
324                                 {
325                                     headcolumnclickevent(a, b);
326                                 }
327                             };
328                             c = lbl;
329                         }
330                         this.pancolumns.controls.add(c, i, 0);
331                     }
332 
333                 }
334             }
335             finally
336             {
337                 controlhelper.freezecontrol(this.panhead, false);
338             }
339         }
340         #endregion
341 
342         /// <summary>
343         /// 功能描述:获取显示个数
344         /// 作  者:hzh
345         /// 创建日期:2019-03-05 10:02:58
346         /// 任务编号:pos
347         /// </summary>
348         /// <returns>返回值</returns>
349         private void resetshowcount()
350         {
351             if (designmode)
352             { return; }
353             showcount = this.panrow.height / (m_rowheight);
354             int intcha = this.panrow.height % (m_rowheight);
355             m_rowheight += intcha / showcount;
356         }
357         #endregion
358 
359         #region 公共函数
360         /// <summary>
361         /// 刷新数据
362         /// </summary>
363         public void reloadsource()
364         {
365             if (designmode)
366             { return; }
367             try
368             {
369                 if (m_columns == null || m_columns.count <= 0)
370                     return;
371 
372                 controlhelper.freezecontrol(this.panrow, true);
373                 this.panrow.controls.clear();
374                 rows = new list<idatagridviewrow>();
375                 if (m_datasource != null)
376                 {
377                     int intindex = 0;
378                     control lastitem = null;
379 
380                     int intsourcecount = 0;
381                     if (m_datasource is datatable)
382                     {
383                         intsourcecount = (m_datasource as datatable).rows.count;
384                     }
385                     else if (typeof(ilist).isassignablefrom(m_datasource.gettype()))
386                     {
387                         intsourcecount = (m_datasource as ilist).count;
388                     }
389 
390                     foreach (control item in this.panrow.controls)
391                     {
392 
393 
394                         if (intindex >= intsourcecount)
395                         {
396                             item.visible = false;
397                         }
398                         else
399                         {
400                             var row = (item as idatagridviewrow);
401                             row.isshowcheckbox = m_isshowcheckbox;
402                             if (m_datasource is datatable)
403                             {
404                                 row.datasource = (m_datasource as datatable).rows[intindex];
405                             }
406                             else
407                             {
408                                 row.datasource = (m_datasource as ilist)[intindex];
409                             }
410                             row.bindingcelldata();
411                             item.height = m_rowheight;
412                             item.visible = true;
413                             item.bringtofront();
414                             if (lastitem == null)
415                                 lastitem = item;
416                             rows.add(row);
417                         }
418                         intindex++;
419                     }
420 
421                     if (intindex < intsourcecount)
422                     {
423                         for (int i = intindex; i < intsourcecount; i++)
424                         {
425                             idatagridviewrow row = (idatagridviewrow)activator.createinstance(m_rowtype);
426                             if (m_datasource is datatable)
427                             {
428                                 row.datasource = (m_datasource as datatable).rows[i];
429                             }
430                             else
431                             {
432                                 row.datasource = (m_datasource as ilist)[i];
433                             }
434                             row.columns = m_columns;
435                             list<control> lstcells = new list<control>();
436                             row.isshowcheckbox = m_isshowcheckbox;
437                             row.reloadcells();
438                             row.bindingcelldata();
439 
440 
441                             control rowcontrol = (row as control);
442                             rowcontrol.height = m_rowheight;
443                             this.panrow.controls.add(rowcontrol);
444                             rowcontrol.dock = dockstyle.top;
445                             row.cellclick += (a, b) => { setselectrow(rowcontrol, b); };
446                             row.checkboxchangeevent += (a, b) => { setselectrow(rowcontrol, b); };
447                             row.sourcechanged += rowsourcechanged;
448                             rowcontrol.bringtofront();
449                             rows.add(row);
450 
451                             if (lastitem == null)
452                                 lastitem = rowcontrol;
453                         }
454                     }
455                     if (lastitem != null && intsourcecount == m_showcount)
456                     {
457                         lastitem.height = this.panrow.height - (m_showcount - 1) * m_rowheight;
458                     }
459                 }
460             }
461             finally
462             {
463                 controlhelper.freezecontrol(this.panrow, false);
464             }
465         }
466 
467 
468         /// <summary>
469         /// 快捷键
470         /// </summary>
471         /// <param name="msg"></param>
472         /// <param name="keydata"></param>
473         /// <returns></returns>
474         protected override bool processcmdkey(ref message msg, keys keydata)
475         {
476             if (keydata == keys.up)
477             {
478                 previous();
479             }
480             else if (keydata == keys.down)
481             {
482                 next();
483             }
484             else if (keydata == keys.home)
485             {
486                 first();
487             }
488             else if (keydata == keys.end)
489             {
490                 end();
491             }
492             return base.processcmdkey(ref msg, keydata);
493         }
494         /// <summary>
495         /// 选中第一个
496         /// </summary>
497         public void first()
498         {
499             if (rows == null || rows.count <= 0)
500                 return;
501             control c = null;
502             c = (rows[0] as control);
503             setselectrow(c, new datagridvieweventargs() { rowindex = 0 });
504         }
505         /// <summary>
506         /// 选中上一个
507         /// </summary>
508         public void previous()
509         {
510             if (rows == null || rows.count <= 0)
511                 return;
512             control c = null;
513 
514             int index = rows.indexof(m_selectrow);
515             if (index - 1 >= 0)
516             {
517                 c = (rows[index - 1] as control);
518                 setselectrow(c, new datagridvieweventargs() { rowindex = index - 1 });
519             }
520         }
521         /// <summary>
522         /// 选中下一个
523         /// </summary>
524         public void next()
525         {
526             if (rows == null || rows.count <= 0)
527                 return;
528             control c = null;
529 
530             int index = rows.indexof(m_selectrow);
531             if (index + 1 < rows.count)
532             {
533                 c = (rows[index + 1] as control);
534                 setselectrow(c, new datagridvieweventargs() { rowindex = index + 1 });
535             }
536         }
537         /// <summary>
538         /// 选中最后一个
539         /// </summary>
540         public void end()
541         {
542             if (rows == null || rows.count <= 0)
543                 return;
544             control c = null;
545             c = (rows[rows.count - 1] as control);
546             setselectrow(c, new datagridvieweventargs() { rowindex = rows.count - 1 });
547         }
548 
549         #endregion
550 
551         #region 事件
552         void rowsourcechanged(object sender, datagridvieweventargs e)
553         {
554             if (sourcechanged != null)
555                 sourcechanged(sender, e);
556         }
557         private void setselectrow(control item, datagridvieweventargs e)
558         {
559             try
560             {
561                 controlhelper.freezecontrol(this, true);
562                 if (item == null)
563                     return;
564                 if (item.visible == false)
565                     return;
566                 this.findform().activecontrol = this;
567                 this.findform().activecontrol = item;
568                 if (m_selectrow != null)
569                 {
570                     if (m_selectrow == item)
571                         return;
572                     m_selectrow.setselect(false);
573                 }
574                 m_selectrow = item as idatagridviewrow;
575                 m_selectrow.setselect(true);
576                 if (itemclick != null)
577                 {
578                     itemclick(item, e);
579                 }
580                 if (this.panrow.controls.count > 0)
581                 {
582                     if (item.location.y < 0)
583                     {
584                         this.panrow.autoscrollposition = new point(0, math.abs(this.panrow.controls[this.panrow.controls.count - 1].location.y) + item.location.y);
585                     }
586                     else if (item.location.y + m_rowheight > this.panrow.height)
587                     {
588                         this.panrow.autoscrollposition = new point(0, math.abs(this.panrow.autoscrollposition.y) + item.location.y - this.panrow.height + m_rowheight);
589                     }
590                 }
591             }
592             finally
593             {
594                 controlhelper.freezecontrol(this, false);
595             }
596         }
597         private void ucdatagridview_resize(object sender, eventargs e)
598         {
599             resetshowcount();
600             reloadsource();
601         }
602         #endregion
603     }
604 }
  1 namespace hzh_controls.controls
2 {
3     partial class ucdatagridview
4     {
5         /// <summary> 
6         /// 必需的设计器变量。
7         /// </summary>
8         private system.componentmodel.icontainer components = null;
9 
10         /// <summary> 
11         /// 清理所有正在使用的资源。
12         /// </summary>
13         /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
14         protected override void dispose(bool disposing)
15         {
16             if (disposing && (components != null))
17             {
18                 components.dispose();
19             }
20             base.dispose(disposing);
21         }
22 
23         #region 组件设计器生成的代码
24 
25         /// <summary> 
26         /// 设计器支持所需的方法 - 不要
27         /// 使用代码编辑器修改此方法的内容。
28         /// </summary>
29         private void initializecomponent()
30         {
31             this.panhead = new system.windows.forms.panel();
32             this.pancolumns = new system.windows.forms.tablelayoutpanel();
33             this.ucsplitline_h1 = new hzh_controls.controls.ucsplitline_h();
34             this.panrow = new system.windows.forms.panel();
35             this.panpage = new system.windows.forms.panel();
36             this.panhead.suspendlayout();
37             this.suspendlayout();
38             // 
39             // panhead
40             // 
41             this.panhead.controls.add(this.pancolumns);
42             this.panhead.controls.add(this.ucsplitline_h1);
43             this.panhead.dock = system.windows.forms.dockstyle.top;
44             this.panhead.location = new system.drawing.point(0, 0);
45             this.panhead.name = "panhead";
46             this.panhead.size = new system.drawing.size(1061, 40);
47             this.panhead.tabindex = 0;
48             // 
49             // pancolumns
50             // 
51             this.pancolumns.columncount = 1;
52             this.pancolumns.columnstyles.add(new system.windows.forms.columnstyle(system.windows.forms.sizetype.percent, 100f));
53             this.pancolumns.dock = system.windows.forms.dockstyle.fill;
54             this.pancolumns.location = new system.drawing.point(0, 0);
55             this.pancolumns.name = "pancolumns";
56             this.pancolumns.rowcount = 1;
57             this.pancolumns.rowstyles.add(new system.windows.forms.rowstyle(system.windows.forms.sizetype.percent, 100f));
58             this.pancolumns.rowstyles.add(new system.windows.forms.rowstyle(system.windows.forms.sizetype.absolute, 20f));
59             this.pancolumns.size = new system.drawing.size(1061, 39);
60             this.pancolumns.tabindex = 1;
61             // 
62             // ucsplitline_h1
63             // 
64             this.ucsplitline_h1.backcolor = system.drawing.color.fromargb(((int)(((byte)(232)))), ((int)(((byte)(232)))), ((int)(((byte)(232)))));
65             this.ucsplitline_h1.dock = system.windows.forms.dockstyle.bottom;
66             this.ucsplitline_h1.location = new system.drawing.point(0, 39);
67             this.ucsplitline_h1.name = "ucsplitline_h1";
68             this.ucsplitline_h1.size = new system.drawing.size(1061, 1);
69             this.ucsplitline_h1.tabindex = 0;
70             this.ucsplitline_h1.tabstop = false;
71             // 
72             // panrow
73             // 
74             this.panrow.autoscroll = true;
75             this.panrow.dock = system.windows.forms.dockstyle.fill;
76             this.panrow.location = new system.drawing.point(0, 40);
77             this.panrow.name = "panrow";
78             this.panrow.size = new system.drawing.size(1061, 475);
79             this.panrow.tabindex = 1;
80             // 
81             // panpage
82             // 
83             this.panpage.dock = system.windows.forms.dockstyle.bottom;
84             this.panpage.location = new system.drawing.point(0, 515);
85             this.panpage.name = "panpage";
86             this.panpage.size = new system.drawing.size(1061, 50);
87             this.panpage.tabindex = 0;
88             this.panpage.visible = false;
89             // 
90             // ucdatagridview
91             // 
92             this.autoscalemode = system.windows.forms.autoscalemode.none;
93             this.backcolor = system.drawing.color.white;
94             this.controls.add(this.panrow);
95             this.controls.add(this.panpage);
96             this.controls.add(this.panhead);
97             this.name = "ucdatagridview";
98             this.size = new system.drawing.size(1061, 565);
99             this.resize += new system.eventhandler(this.ucdatagridview_resize);
100             this.panhead.resumelayout(false);
101             this.resumelayout(false);
102 
103         }
104 
105         #endregion
106 
107         private system.windows.forms.panel panhead;
108         private system.windows.forms.tablelayoutpanel pancolumns;
109         private ucsplitline_h ucsplitline_h1;
110         private system.windows.forms.panel panrow;
111         private system.windows.forms.panel panpage;
112 
113     }
114 }

如果你仔细看,你会发现行我用了类型进行传入,当你需要更丰富的行内容的时候,可以自定义行控件,然后通过rowtype属性传入

分页控件我使用了分页控件基类ucpagercontrolbase,这样做的好处就是你同样可以扩展分页控件

用处及效果

调用示例

 1  list<datagridviewcolumnentity> lstculumns = new list<datagridviewcolumnentity>();
2             lstculumns.add(new datagridviewcolumnentity() { datafield = "id", headtext = "编号", width = 70, widthtype = sizetype.absolute });
3             lstculumns.add(new datagridviewcolumnentity() { datafield = "name", headtext = "姓名", width = 50, widthtype = sizetype.percent });
4             lstculumns.add(new datagridviewcolumnentity() { datafield = "age", headtext = "年龄", width = 50, widthtype = sizetype.percent });
5             lstculumns.add(new datagridviewcolumnentity() { datafield = "birthday", headtext = "生日", width = 50, widthtype = sizetype.percent, format = (a) => { return ((datetime)a).tostring("yyyy-mm-dd"); } });
6             lstculumns.add(new datagridviewcolumnentity() { datafield = "sex", headtext = "性别", width = 50, widthtype = sizetype.percent, format = (a) => { return ((int)a) == 0 ? "女" : "男"; } });
7             this.ucdatagridview1.columns = lstculumns;
8             this.ucdatagridview1.isshowcheckbox = true;
9             list<object> lstsource = new list<object>();
10             for (int i = 0; i < 200; i++)
11             {
12                 testmodel model = new testmodel()
13                 {
14                     id = i.tostring(),
15                     age = 3 * i,
16                     name = "姓名——" + i,
17                     birthday = datetime.now.addyears(-10),
18                     sex = i % 2
19                 };
20                 lstsource.add(model);
21             }
22 
23             var page = new ucpagercontrol2();
24             page.datasource = lstsource;
25             this.ucdatagridview1.page = page;
26             this.ucdatagridview1.first();

如果使用分页控件,则将数据源指定给分页控件,否则直接指定给表格控件数据源

最后的话

如果你喜欢的话,请到  点个星 星吧