(十)c#Winform自定义控件-横向列表

官网

http://www.hzhcontrols.com

前提

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

GitHub:https://github.com/kwwwvagaa/NetWinformControl

码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git

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

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

目录

https://www.cnblogs.com/bfyx/p/11364884.html

准备工作

梳理一下需求,我们需要一个横向的节点列表控件,可以进行左右翻页

根据上面所写的需求,我们需要分为2步操作,1:创建项控件,2:创建列表控件

开始

首先我们创建项控件,添加一个用户控件,命名UCHorizontalListItem

代码量并不多,我们看下完整代码

 1 // 版权所有  黄正辉  交流群:568015492   QQ:623128629
 2 // 文件名称:UCHorizontalListItem.cs
 3 // 创建日期:2019-08-15 16:01:13
 4 // 功能描述:HorizontalList
 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 UCHorizontalListItem : UserControl
19     {
20         public event EventHandler SelectedItem;
21         private KeyValuePair<string, string> _DataSource = new KeyValuePair<string, string>();
22         public KeyValuePair<string, string> DataSource
23         {
24             get { return _DataSource; }
25             set
26             {
27                 _DataSource = value;
28                 int intWidth = ControlHelper.GetStringWidth(value.Value, lblTitle.CreateGraphics(), lblTitle.Font);
29                 if (intWidth < 50)
30                     intWidth = 50;
31                 this.Width = intWidth + 20;
32                 lblTitle.Text = value.Value;
33                 SetSelect(false);
34             }
35         }
36         public UCHorizontalListItem()
37         {
38             InitializeComponent();
39             this.Dock = DockStyle.Right;
40             this.MouseDown += Item_MouseDown;
41             this.lblTitle.MouseDown += Item_MouseDown;
42             this.ucSplitLine_H1.MouseDown += Item_MouseDown;
43         }
44 
45         void Item_MouseDown(object sender, MouseEventArgs e)
46         {
47             if (SelectedItem != null)
48                 SelectedItem(this, e);
49         }
50 
51         public void SetSelect(bool bln)
52         {
53             if (bln)
54             {
55                 lblTitle.ForeColor = Color.FromArgb(255, 77, 59);
56                 ucSplitLine_H1.Visible = true;
57                 this.lblTitle.Padding = new Padding(0, 0, 0, 5);
58             }
59             else
60             {
61                 lblTitle.ForeColor = Color.FromArgb(64, 64, 64);
62                 ucSplitLine_H1.Visible = false;
63                 this.lblTitle.Padding = new Padding(0, 0, 0, 0);
64             }
65         }
66     }
67 }
View Code
 1 namespace HZH_Controls.Controls
 2 {
 3     partial class UCHorizontalListItem
 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.lblTitle = new System.Windows.Forms.Label();
32             this.ucSplitLine_H1 = new HZH_Controls.Controls.UCSplitLine_H();
33             this.SuspendLayout();
34             // 
35             // lblTitle
36             // 
37             this.lblTitle.Dock = System.Windows.Forms.DockStyle.Fill;
38             this.lblTitle.Font = new System.Drawing.Font("微软雅黑", 10F);
39             this.lblTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
40             this.lblTitle.Location = new System.Drawing.Point(1, 0);
41             this.lblTitle.Name = "lblTitle";
42             this.lblTitle.Padding = new System.Windows.Forms.Padding(0, 0, 0, 10);
43             this.lblTitle.Size = new System.Drawing.Size(118, 50);
44             this.lblTitle.TabIndex = 1;
45             this.lblTitle.Text = "分类名称\r\n分类名称";
46             this.lblTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
47             // 
48             // ucSplitLine_H1
49             // 
50             this.ucSplitLine_H1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(77)))), ((int)(((byte)(59)))));
51             this.ucSplitLine_H1.Dock = System.Windows.Forms.DockStyle.Bottom;
52             this.ucSplitLine_H1.Location = new System.Drawing.Point(1, 50);
53             this.ucSplitLine_H1.Name = "ucSplitLine_H1";
54             this.ucSplitLine_H1.Size = new System.Drawing.Size(118, 3);
55             this.ucSplitLine_H1.TabIndex = 0;
56             this.ucSplitLine_H1.TabStop = false;
57             // 
58             // UCHorizontalListItem
59             // 
60             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
61             this.Controls.Add(this.lblTitle);
62             this.Controls.Add(this.ucSplitLine_H1);
63             this.Name = "UCHorizontalListItem";
64             this.Padding = new System.Windows.Forms.Padding(1, 0, 1, 0);
65             this.Size = new System.Drawing.Size(120, 53);
66             this.ResumeLayout(false);
67 
68         }
69 
70         #endregion
71 
72         private UCSplitLine_H ucSplitLine_H1;
73         private System.Windows.Forms.Label lblTitle;
74     }
75 }
View Code

设计效果如图

 

接着我们来创建列表控件,添加一个用户控件,命名UCHorizontalList

我们看下需要提供哪些属性

public UCHorizontalListItem SelectedItem { get; set; }
        public event EventHandler SelectedItemEvent;
        private int m_startItemIndex = 0;
        private bool isAutoSelectFirst = true;

        public bool IsAutoSelectFirst
        {
            get { return isAutoSelectFirst; }
            set { isAutoSelectFirst = value; }
        }

        private List<KeyValuePair<string, string>> dataSource = null;

        public List<KeyValuePair<string, string>> DataSource
        {
            get { return dataSource; }
            set
            {
                dataSource = value;
                ReloadSource();
            }
        }

我们有时需要刷新列表

 1  public void ReloadSource()
 2         {
 3             try
 4             {
 5                 ControlHelper.FreezeControl(this, true);
 6                 this.panList.SuspendLayout();
 7                 this.panList.Controls.Clear();
 8                 this.panList.Width = this.panMain.Width;
 9                 if (DataSource != null)
10                 {
11                     foreach (var item in DataSource)
12                     {
13                         UCHorizontalListItem uc = new UCHorizontalListItem();
14                         uc.DataSource = item;
15                         uc.SelectedItem += uc_SelectItem;
16                         this.panList.Controls.Add(uc);
17                     }
18                 }
19                 this.panList.ResumeLayout(true);
20                 if (this.panList.Controls.Count > 0)
21                     this.panList.Width = panMain.Width + this.panList.Controls[0].Location.X * -1;
22                 this.panList.Location = new Point(0, 0);
23                 m_startItemIndex = 0;
24                 if (this.panList.Width > panMain.Width)
25                     panRight.Visible = true;
26                 else
27                     panRight.Visible = false;
28                 panLeft.Visible = false;
29                 panList.SendToBack();
30                 panRight.SendToBack();
31                 if (isAutoSelectFirst && DataSource != null && DataSource.Count > 0)
32                 {
33                     SelectItem((UCHorizontalListItem)this.panList.Controls[0]);
34                 }
35             }
36             finally
37             {
38                 ControlHelper.FreezeControl(this, false);
39             }
40         }

还需要处理选中处理

1  private void SelectItem(UCHorizontalListItem item)
2         {
3             if (SelectedItem != null && !SelectedItem.IsDisposed)
4                 SelectedItem.SetSelect(false);
5             SelectedItem = item;
6             SelectedItem.SetSelect(true);
7             if (SelectedItemEvent != null)
8                 SelectedItemEvent(item, null);
9         }

然后就是翻页功能的处理了

 1  private void panLeft_MouseDown(object sender, MouseEventArgs e)
 2         {
 3             if (this.panList.Location.X >= 0)
 4             {
 5                 this.panList.Location = new Point(0, 0);
 6                 return;
 7             }
 8 
 9             for (int i = m_startItemIndex; i >= 0; i--)
10             {
11                 if (this.panList.Controls[i].Location.X < this.panList.Controls[m_startItemIndex].Location.X - panMain.Width)
12                 {
13                     m_startItemIndex = i + 1;
14                     break; ;
15                 }
16                 if (i == 0)
17                 {
18                     m_startItemIndex = 0;
19                 }
20             }
21 
22             ResetListLocation();
23             panRight.Visible = true;
24             if (this.panList.Location.X >= 0)
25             {
26                 panLeft.Visible = false;
27             }
28             else
29             {
30                 panLeft.Visible = true;
31             }
32             panList.SendToBack();
33             panRight.SendToBack();
34         }
35 
36         private void panRight_MouseDown(object sender, MouseEventArgs e)
37         {
38             if (this.panList.Location.X + this.panList.Width <= this.panMain.Width)
39                 return;
40             if (this.panList.Controls.Count <= 0)
41                 return;
42             for (int i = m_startItemIndex; i < this.panList.Controls.Count; i++)
43             {
44                 if (this.panList.Location.X + this.panList.Controls[i].Location.X + this.panList.Controls[i].Width > panMain.Width)
45                 {
46                     m_startItemIndex = i;
47                     break;
48                 }
49             }
50             ResetListLocation();
51             panLeft.Visible = true;
52             if (panList.Width + panList.Location.X <= panMain.Width)
53                 panRight.Visible = false;
54             else
55                 panRight.Visible = true;
56             panList.SendToBack();
57             panRight.SendToBack();
58         }
59 
60         private void ResetListLocation()
61         {
62             if (this.panList.Controls.Count > 0)
63             {
64                 this.panList.Location = new Point(this.panList.Controls[m_startItemIndex].Location.X * -1, 0);
65             }
66         }

最后向外暴露一个设置选中的功能

 1 public void SetSelect(string strKey)
 2         {
 3             foreach (UCHorizontalListItem item in this.panList.Controls)
 4             {
 5                 if (item.DataSource.Key == strKey)
 6                 {
 7                     SelectItem(item);
 8                     return;
 9                 }
10             }
11         }

以上就是主要东西了,再看下完整代码

  1 // 版权所有  黄正辉  交流群:568015492   QQ:623128629
  2 // 文件名称:UCHorizontalList.cs
  3 // 创建日期:2019-08-15 16:01:06
  4 // 功能描述:HorizontalList
  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     public partial class UCHorizontalList : UserControl
 18     {
 19         public UCHorizontalListItem SelectedItem { get; set; }
 20         public event EventHandler SelectedItemEvent;
 21         private int m_startItemIndex = 0;
 22         private bool isAutoSelectFirst = true;
 23 
 24         public bool IsAutoSelectFirst
 25         {
 26             get { return isAutoSelectFirst; }
 27             set { isAutoSelectFirst = value; }
 28         }
 29 
 30         private List<KeyValuePair<string, string>> dataSource = null;
 31 
 32         public List<KeyValuePair<string, string>> DataSource
 33         {
 34             get { return dataSource; }
 35             set
 36             {
 37                 dataSource = value;
 38                 ReloadSource();
 39             }
 40         }
 41 
 42         public UCHorizontalList()
 43         {
 44             InitializeComponent();
 45         }
 46 
 47         public void ReloadSource()
 48         {
 49             try
 50             {
 51                 ControlHelper.FreezeControl(this, true);
 52                 this.panList.SuspendLayout();
 53                 this.panList.Controls.Clear();
 54                 this.panList.Width = this.panMain.Width;
 55                 if (DataSource != null)
 56                 {
 57                     foreach (var item in DataSource)
 58                     {
 59                         UCHorizontalListItem uc = new UCHorizontalListItem();
 60                         uc.DataSource = item;
 61                         uc.SelectedItem += uc_SelectItem;
 62                         this.panList.Controls.Add(uc);
 63                     }
 64                 }
 65                 this.panList.ResumeLayout(true);
 66                 if (this.panList.Controls.Count > 0)
 67                     this.panList.Width = panMain.Width + this.panList.Controls[0].Location.X * -1;
 68                 this.panList.Location = new Point(0, 0);
 69                 m_startItemIndex = 0;
 70                 if (this.panList.Width > panMain.Width)
 71                     panRight.Visible = true;
 72                 else
 73                     panRight.Visible = false;
 74                 panLeft.Visible = false;
 75                 panList.SendToBack();
 76                 panRight.SendToBack();
 77                 if (isAutoSelectFirst && DataSource != null && DataSource.Count > 0)
 78                 {
 79                     SelectItem((UCHorizontalListItem)this.panList.Controls[0]);
 80                 }
 81             }
 82             finally
 83             {
 84                 ControlHelper.FreezeControl(this, false);
 85             }
 86         }
 87 
 88         void uc_SelectItem(object sender, EventArgs e)
 89         {
 90             SelectItem(sender as UCHorizontalListItem);
 91         }
 92 
 93         private void SelectItem(UCHorizontalListItem item)
 94         {
 95             if (SelectedItem != null && !SelectedItem.IsDisposed)
 96                 SelectedItem.SetSelect(false);
 97             SelectedItem = item;
 98             SelectedItem.SetSelect(true);
 99             if (SelectedItemEvent != null)
100                 SelectedItemEvent(item, null);
101         }
102 
103         private void panLeft_MouseDown(object sender, MouseEventArgs e)
104         {
105             if (this.panList.Location.X >= 0)
106             {
107                 this.panList.Location = new Point(0, 0);
108                 return;
109             }
110 
111             for (int i = m_startItemIndex; i >= 0; i--)
112             {
113                 if (this.panList.Controls[i].Location.X < this.panList.Controls[m_startItemIndex].Location.X - panMain.Width)
114                 {
115                     m_startItemIndex = i + 1;
116                     break; ;
117                 }
118                 if (i == 0)
119                 {
120                     m_startItemIndex = 0;
121                 }
122             }
123 
124             ResetListLocation();
125             panRight.Visible = true;
126             if (this.panList.Location.X >= 0)
127             {
128                 panLeft.Visible = false;
129             }
130             else
131             {
132                 panLeft.Visible = true;
133             }
134             panList.SendToBack();
135             panRight.SendToBack();
136         }
137 
138         private void panRight_MouseDown(object sender, MouseEventArgs e)
139         {
140             if (this.panList.Location.X + this.panList.Width <= this.panMain.Width)
141                 return;
142             if (this.panList.Controls.Count <= 0)
143                 return;
144             for (int i = m_startItemIndex; i < this.panList.Controls.Count; i++)
145             {
146                 if (this.panList.Location.X + this.panList.Controls[i].Location.X + this.panList.Controls[i].Width > panMain.Width)
147                 {
148                     m_startItemIndex = i;
149                     break;
150                 }
151             }
152             ResetListLocation();
153             panLeft.Visible = true;
154             if (panList.Width + panList.Location.X <= panMain.Width)
155                 panRight.Visible = false;
156             else
157                 panRight.Visible = true;
158             panList.SendToBack();
159             panRight.SendToBack();
160         }
161 
162         private void ResetListLocation()
163         {
164             if (this.panList.Controls.Count > 0)
165             {
166                 this.panList.Location = new Point(this.panList.Controls[m_startItemIndex].Location.X * -1, 0);
167             }
168         }
169 
170         public void SetSelect(string strKey)
171         {
172             foreach (UCHorizontalListItem item in this.panList.Controls)
173             {
174                 if (item.DataSource.Key == strKey)
175                 {
176                     SelectItem(item);
177                     return;
178                 }
179             }
180         }
181     }
182 }
View Code
  1 namespace HZH_Controls.Controls
  2 {
  3     partial class UCHorizontalList
  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.panMain = new System.Windows.Forms.Panel();
 32             this.panList = new System.Windows.Forms.Panel();
 33             this.panRight = new System.Windows.Forms.Panel();
 34             this.panLeft = new System.Windows.Forms.Panel();
 35             this.panMain.SuspendLayout();
 36             this.SuspendLayout();
 37             // 
 38             // panMain
 39             // 
 40             this.panMain.Controls.Add(this.panList);
 41             this.panMain.Dock = System.Windows.Forms.DockStyle.Fill;
 42             this.panMain.Location = new System.Drawing.Point(46, 0);
 43             this.panMain.Name = "panMain";
 44             this.panMain.Size = new System.Drawing.Size(422, 53);
 45             this.panMain.TabIndex = 3;
 46             // 
 47             // panList
 48             // 
 49             this.panList.Anchor = System.Windows.Forms.AnchorStyles.Left;
 50             this.panList.BackColor = System.Drawing.Color.Transparent;
 51             this.panList.Location = new System.Drawing.Point(0, 0);
 52             this.panList.Name = "panList";
 53             this.panList.Size = new System.Drawing.Size(401, 53);
 54             this.panList.TabIndex = 0;
 55             // 
 56             // panRight
 57             // 
 58             this.panRight.BackgroundImage = global::HZH_Controls.Properties.Resources.chevron_right;
 59             this.panRight.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
 60             this.panRight.Dock = System.Windows.Forms.DockStyle.Right;
 61             this.panRight.Location = new System.Drawing.Point(468, 0);
 62             this.panRight.Name = "panRight";
 63             this.panRight.Size = new System.Drawing.Size(46, 53);
 64             this.panRight.TabIndex = 2;
 65             this.panRight.Visible = false;
 66             this.panRight.MouseDown += new System.Windows.Forms.MouseEventHandler(this.panRight_MouseDown);
 67             // 
 68             // panLeft
 69             // 
 70             this.panLeft.BackgroundImage = global::HZH_Controls.Properties.Resources.chevron_left;
 71             this.panLeft.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
 72             this.panLeft.Dock = System.Windows.Forms.DockStyle.Left;
 73             this.panLeft.Location = new System.Drawing.Point(0, 0);
 74             this.panLeft.Name = "panLeft";
 75             this.panLeft.Size = new System.Drawing.Size(46, 53);
 76             this.panLeft.TabIndex = 1;
 77             this.panLeft.Visible = false;
 78             this.panLeft.MouseDown += new System.Windows.Forms.MouseEventHandler(this.panLeft_MouseDown);
 79             // 
 80             // UCHorizontalList
 81             // 
 82             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
 83             this.Controls.Add(this.panMain);
 84             this.Controls.Add(this.panRight);
 85             this.Controls.Add(this.panLeft);
 86             this.Name = "UCHorizontalList";
 87             this.Size = new System.Drawing.Size(514, 53);
 88             this.panMain.ResumeLayout(false);
 89             this.ResumeLayout(false);
 90 
 91         }
 92 
 93         #endregion
 94 
 95         private System.Windows.Forms.Panel panLeft;
 96         private System.Windows.Forms.Panel panRight;
 97         private System.Windows.Forms.Panel panMain;
 98         private System.Windows.Forms.Panel panList;
 99     }
100 }
View Code

用处及效果

用处:一般用着需要横向切换选项的地方,比如省份切换等

效果:

 

调用示例

1  List<KeyValuePair<string, string>> lstHL = new List<KeyValuePair<string, string>>();
2             for (int i = 0; i < 30; i++)
3             {
4                 lstHL.Add(new KeyValuePair<string, string>(i.ToString(), "选项" + i));
5             }
6 
7             this.ucHorizontalList1.DataSource = lstHL;

 

最后的话

如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星 星吧

posted @ 2019-08-16 10:51 冰封一夏 阅读(...) 评论(...) 编辑 收藏
HZHControls控件库官网:http://hzhcontrols.com