premise
Having been in business for 7,8 years and always wanted to make a beautiful set of custom controls, this series of articles came out.
GitHub: https://github.com/kwwwvagaa/NetWinformControl
Yak Yun: https://gitee.com/kwwwvagaa/net_winform_custom_control.git
If you think the writing is OK, please click a star to support it
Welcome to the exchange: Penguins 568015492
Catalog
https://blog.csdn.net/kwwwvagaa/article/details/100586547
Dead work
To sort out the requirements, we need a horizontal node list control that can flip left and right
Based on the requirements described above, we need to divide into two steps: 1: Create item control, 2: Create list control
start
First we create an item control, add a user control, and name UCHorizontalListItem
Not a lot of code, let's look at the complete code
// Copyright All Huang Zhenghui Exchange Group: 568015492 QQ:623128629 // File name: UCHorizontalListItem.cs // Creation date: 2019-08-15 16:01:13 // Capability description: HorizontalList // Project address: https://gitee.com/kwwvagaa/net_winform_custom_control using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; namespace HZH_Controls.Controls { [ToolboxItem(false)] public partial class UCHorizontalListItem : UserControl { public event EventHandler SelectedItem; private KeyValuePair<string, string> _DataSource = new KeyValuePair<string, string>(); public KeyValuePair<string, string> DataSource { get { return _DataSource; } set { _DataSource = value; int intWidth = ControlHelper.GetStringWidth(value.Value, lblTitle.CreateGraphics(), lblTitle.Font); if (intWidth < 50) intWidth = 50; this.Width = intWidth + 20; lblTitle.Text = value.Value; SetSelect(false); } } public UCHorizontalListItem() { InitializeComponent(); this.Dock = DockStyle.Right; this.MouseDown += Item_MouseDown; this.lblTitle.MouseDown += Item_MouseDown; this.ucSplitLine_H1.MouseDown += Item_MouseDown; } void Item_MouseDown(object sender, MouseEventArgs e) { if (SelectedItem != null) SelectedItem(this, e); } public void SetSelect(bool bln) { if (bln) { lblTitle.ForeColor = Color.FromArgb(255, 77, 59); ucSplitLine_H1.Visible = true; this.lblTitle.Padding = new Padding(0, 0, 0, 5); } else { lblTitle.ForeColor = Color.FromArgb(64, 64, 64); ucSplitLine_H1.Visible = false; this.lblTitle.Padding = new Padding(0, 0, 0, 0); } } } }
namespace HZH_Controls.Controls { partial class UCHorizontalListItem { /// <summary> ///Required designer variables. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> ///Clean up all resources in use. /// </summary> /// <param name="disposing">true if managed resources should be released; otherwise false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer Generated Code /// <summary> ///Designer supports required methods - Do not ///Use the code editor to modify the contents of this method. /// </summary> private void InitializeComponent() { this.lblTitle = new System.Windows.Forms.Label(); this.ucSplitLine_H1 = new HZH_Controls.Controls.UCSplitLine_H(); this.SuspendLayout(); // // lblTitle // this.lblTitle.Dock = System.Windows.Forms.DockStyle.Fill; this.lblTitle.Font = new System.Drawing.Font("Microsoft YaHei", 10F); this.lblTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); this.lblTitle.Location = new System.Drawing.Point(1, 0); this.lblTitle.Name = "lblTitle"; this.lblTitle.Padding = new System.Windows.Forms.Padding(0, 0, 0, 10); this.lblTitle.Size = new System.Drawing.Size(118, 50); this.lblTitle.TabIndex = 1; this.lblTitle.Text = "Category name\r\n Category name"; this.lblTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // ucSplitLine_H1 // this.ucSplitLine_H1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(77)))), ((int)(((byte)(59))))); this.ucSplitLine_H1.Dock = System.Windows.Forms.DockStyle.Bottom; this.ucSplitLine_H1.Location = new System.Drawing.Point(1, 50); this.ucSplitLine_H1.Name = "ucSplitLine_H1"; this.ucSplitLine_H1.Size = new System.Drawing.Size(118, 3); this.ucSplitLine_H1.TabIndex = 0; this.ucSplitLine_H1.TabStop = false; // // UCHorizontalListItem // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; this.Controls.Add(this.lblTitle); this.Controls.Add(this.ucSplitLine_H1); this.Name = "UCHorizontalListItem"; this.Padding = new System.Windows.Forms.Padding(1, 0, 1, 0); this.Size = new System.Drawing.Size(120, 53); this.ResumeLayout(false); } #endregion private UCSplitLine_H ucSplitLine_H1; private System.Windows.Forms.Label lblTitle; } }
Design effect as shown in the diagram
Next, let's create a list control, add a user control, and name UCHorizontalList
Let's see what attributes we need to provide
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(); } }
Sometimes we need to refresh the list
public void ReloadSource() { try { ControlHelper.FreezeControl(this, true); this.panList.SuspendLayout(); this.panList.Controls.Clear(); this.panList.Width = this.panMain.Width; if (DataSource != null) { foreach (var item in DataSource) { UCHorizontalListItem uc = new UCHorizontalListItem(); uc.DataSource = item; uc.SelectedItem += uc_SelectItem; this.panList.Controls.Add(uc); } } this.panList.ResumeLayout(true); if (this.panList.Controls.Count > 0) this.panList.Width = panMain.Width + this.panList.Controls[0].Location.X * -1; this.panList.Location = new Point(0, 0); m_startItemIndex = 0; if (this.panList.Width > panMain.Width) panRight.Visible = true; else panRight.Visible = false; panLeft.Visible = false; panList.SendToBack(); panRight.SendToBack(); if (isAutoSelectFirst && DataSource != null && DataSource.Count > 0) { SelectItem((UCHorizontalListItem)this.panList.Controls[0]); } } finally { ControlHelper.FreezeControl(this, false); } }
Selected processing is also required
private void SelectItem(UCHorizontalListItem item) { if (SelectedItem != null && !SelectedItem.IsDisposed) SelectedItem.SetSelect(false); SelectedItem = item; SelectedItem.SetSelect(true); if (SelectedItemEvent != null) SelectedItemEvent(item, null); }
Then there's the paging function
private void panLeft_MouseDown(object sender, MouseEventArgs e) { if (this.panList.Location.X >= 0) { this.panList.Location = new Point(0, 0); return; } for (int i = m_startItemIndex; i >= 0; i--) { if (this.panList.Controls[i].Location.X < this.panList.Controls[m_startItemIndex].Location.X - panMain.Width) { m_startItemIndex = i + 1; break; ; } if (i == 0) { m_startItemIndex = 0; } } ResetListLocation(); panRight.Visible = true; if (this.panList.Location.X >= 0) { panLeft.Visible = false; } else { panLeft.Visible = true; } panList.SendToBack(); panRight.SendToBack(); } private void panRight_MouseDown(object sender, MouseEventArgs e) { if (this.panList.Location.X + this.panList.Width <= this.panMain.Width) return; if (this.panList.Controls.Count <= 0) return; for (int i = m_startItemIndex; i < this.panList.Controls.Count; i++) { if (this.panList.Location.X + this.panList.Controls[i].Location.X + this.panList.Controls[i].Width > panMain.Width) { m_startItemIndex = i; break; } } ResetListLocation(); panLeft.Visible = true; if (panList.Width + panList.Location.X <= panMain.Width) panRight.Visible = false; else panRight.Visible = true; panList.SendToBack(); panRight.SendToBack(); } private void ResetListLocation() { if (this.panList.Controls.Count > 0) { this.panList.Location = new Point(this.panList.Controls[m_startItemIndex].Location.X * -1, 0); } }
Finally expose one of the settings selected
public void SetSelect(string strKey) { foreach (UCHorizontalListItem item in this.panList.Controls) { if (item.DataSource.Key == strKey) { SelectItem(item); return; } } }
That's the main thing. Look at the complete code
// Copyright All Huang Zhenghui Exchange Group: 568015492 QQ:623128629 // File name: UCHorizontalList.cs // Creation date: 2019-08-15 16:01:06 // Capability description: HorizontalList // Project address: https://gitee.com/kwwvagaa/net_winform_custom_control using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; namespace HZH_Controls.Controls { public partial class UCHorizontalList : UserControl { 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(); } } public UCHorizontalList() { InitializeComponent(); } public void ReloadSource() { try { ControlHelper.FreezeControl(this, true); this.panList.SuspendLayout(); this.panList.Controls.Clear(); this.panList.Width = this.panMain.Width; if (DataSource != null) { foreach (var item in DataSource) { UCHorizontalListItem uc = new UCHorizontalListItem(); uc.DataSource = item; uc.SelectedItem += uc_SelectItem; this.panList.Controls.Add(uc); } } this.panList.ResumeLayout(true); if (this.panList.Controls.Count > 0) this.panList.Width = panMain.Width + this.panList.Controls[0].Location.X * -1; this.panList.Location = new Point(0, 0); m_startItemIndex = 0; if (this.panList.Width > panMain.Width) panRight.Visible = true; else panRight.Visible = false; panLeft.Visible = false; panList.SendToBack(); panRight.SendToBack(); if (isAutoSelectFirst && DataSource != null && DataSource.Count > 0) { SelectItem((UCHorizontalListItem)this.panList.Controls[0]); } } finally { ControlHelper.FreezeControl(this, false); } } void uc_SelectItem(object sender, EventArgs e) { SelectItem(sender as UCHorizontalListItem); } private void SelectItem(UCHorizontalListItem item) { if (SelectedItem != null && !SelectedItem.IsDisposed) SelectedItem.SetSelect(false); SelectedItem = item; SelectedItem.SetSelect(true); if (SelectedItemEvent != null) SelectedItemEvent(item, null); } private void panLeft_MouseDown(object sender, MouseEventArgs e) { if (this.panList.Location.X >= 0) { this.panList.Location = new Point(0, 0); return; } for (int i = m_startItemIndex; i >= 0; i--) { if (this.panList.Controls[i].Location.X < this.panList.Controls[m_startItemIndex].Location.X - panMain.Width) { m_startItemIndex = i + 1; break; ; } if (i == 0) { m_startItemIndex = 0; } } ResetListLocation(); panRight.Visible = true; if (this.panList.Location.X >= 0) { panLeft.Visible = false; } else { panLeft.Visible = true; } panList.SendToBack(); panRight.SendToBack(); } private void panRight_MouseDown(object sender, MouseEventArgs e) { if (this.panList.Location.X + this.panList.Width <= this.panMain.Width) return; if (this.panList.Controls.Count <= 0) return; for (int i = m_startItemIndex; i < this.panList.Controls.Count; i++) { if (this.panList.Location.X + this.panList.Controls[i].Location.X + this.panList.Controls[i].Width > panMain.Width) { m_startItemIndex = i; break; } } ResetListLocation(); panLeft.Visible = true; if (panList.Width + panList.Location.X <= panMain.Width) panRight.Visible = false; else panRight.Visible = true; panList.SendToBack(); panRight.SendToBack(); } private void ResetListLocation() { if (this.panList.Controls.Count > 0) { this.panList.Location = new Point(this.panList.Controls[m_startItemIndex].Location.X * -1, 0); } } public void SetSelect(string strKey) { foreach (UCHorizontalListItem item in this.panList.Controls) { if (item.DataSource.Key == strKey) { SelectItem(item); return; } } } } }
namespace HZH_Controls.Controls { partial class UCHorizontalList { /// <summary> ///Required designer variables. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> ///Clean up all resources in use. /// </summary> /// <param name="disposing">true if managed resources should be released; otherwise false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer Generated Code /// <summary> ///Designer supports required methods - Do not ///Use the code editor to modify the contents of this method. /// </summary> private void InitializeComponent() { this.panMain = new System.Windows.Forms.Panel(); this.panList = new System.Windows.Forms.Panel(); this.panRight = new System.Windows.Forms.Panel(); this.panLeft = new System.Windows.Forms.Panel(); this.panMain.SuspendLayout(); this.SuspendLayout(); // // panMain // this.panMain.Controls.Add(this.panList); this.panMain.Dock = System.Windows.Forms.DockStyle.Fill; this.panMain.Location = new System.Drawing.Point(46, 0); this.panMain.Name = "panMain"; this.panMain.Size = new System.Drawing.Size(422, 53); this.panMain.TabIndex = 3; // // panList // this.panList.Anchor = System.Windows.Forms.AnchorStyles.Left; this.panList.BackColor = System.Drawing.Color.Transparent; this.panList.Location = new System.Drawing.Point(0, 0); this.panList.Name = "panList"; this.panList.Size = new System.Drawing.Size(401, 53); this.panList.TabIndex = 0; // // panRight // this.panRight.BackgroundImage = global::HZH_Controls.Properties.Resources.chevron_right; this.panRight.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; this.panRight.Dock = System.Windows.Forms.DockStyle.Right; this.panRight.Location = new System.Drawing.Point(468, 0); this.panRight.Name = "panRight"; this.panRight.Size = new System.Drawing.Size(46, 53); this.panRight.TabIndex = 2; this.panRight.Visible = false; this.panRight.MouseDown += new System.Windows.Forms.MouseEventHandler(this.panRight_MouseDown); // // panLeft // this.panLeft.BackgroundImage = global::HZH_Controls.Properties.Resources.chevron_left; this.panLeft.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; this.panLeft.Dock = System.Windows.Forms.DockStyle.Left; this.panLeft.Location = new System.Drawing.Point(0, 0); this.panLeft.Name = "panLeft"; this.panLeft.Size = new System.Drawing.Size(46, 53); this.panLeft.TabIndex = 1; this.panLeft.Visible = false; this.panLeft.MouseDown += new System.Windows.Forms.MouseEventHandler(this.panLeft_MouseDown); // // UCHorizontalList // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; this.Controls.Add(this.panMain); this.Controls.Add(this.panRight); this.Controls.Add(this.panLeft); this.Name = "UCHorizontalList"; this.Size = new System.Drawing.Size(514, 53); this.panMain.ResumeLayout(false); this.ResumeLayout(false); } #endregion private System.Windows.Forms.Panel panLeft; private System.Windows.Forms.Panel panRight; private System.Windows.Forms.Panel panMain; private System.Windows.Forms.Panel panList; } }
Uses and effects
Usefulness: Usually in places where horizontal switching options are needed, such as provincial switching, etc.
Effect:
Call example
List<KeyValuePair<string, string>> lstHL = new List<KeyValuePair<string, string>>(); for (int i = 0; i < 30; i++) { lstHL.Add(new KeyValuePair<string, string>(i.ToString(), "option" + i)); } this.ucHorizontalList1.DataSource = lstHL;
Last words
If you like, please come to https://gitee.com/kwwwvagaa/net_winform_custom_control Point a star