官网

http://www.hzhcontrols.com

前提

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

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

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

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

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

idkey=6e08741ef16fe53bf0314c1c9e336c4f626047943a8b76bac062361bab6b4f8d">

目录

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

准备工作

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

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

开始

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

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

 // 版权所有  黄正辉  交流群:568015492   QQ:623128629
// 文件名称:UCHorizontalListItem.cs
// 创建日期:2019-08-15 16:01:13
// 功能描述:HorizontalList
// 项目地址:https://gitee.com/kwwwvagaa/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 < )
intWidth = ;
this.Width = intWidth + ;
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(, , );
ucSplitLine_H1.Visible = true;
this.lblTitle.Padding = new Padding(, , , );
}
else
{
lblTitle.ForeColor = Color.FromArgb(, , );
ucSplitLine_H1.Visible = false;
this.lblTitle.Padding = new Padding(, , , );
}
}
}
}
 namespace HZH_Controls.Controls
{
partial class UCHorizontalListItem
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null; /// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
} #region 组件设计器生成的代码 /// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </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("微软雅黑", 10F);
this.lblTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)()))), ((int)(((byte)()))), ((int)(((byte)()))));
this.lblTitle.Location = new System.Drawing.Point(, );
this.lblTitle.Name = "lblTitle";
this.lblTitle.Padding = new System.Windows.Forms.Padding(, , , );
this.lblTitle.Size = new System.Drawing.Size(, );
this.lblTitle.TabIndex = ;
this.lblTitle.Text = "分类名称\r\n分类名称";
this.lblTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// ucSplitLine_H1
//
this.ucSplitLine_H1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)()))), ((int)(((byte)()))), ((int)(((byte)()))));
this.ucSplitLine_H1.Dock = System.Windows.Forms.DockStyle.Bottom;
this.ucSplitLine_H1.Location = new System.Drawing.Point(, );
this.ucSplitLine_H1.Name = "ucSplitLine_H1";
this.ucSplitLine_H1.Size = new System.Drawing.Size(, );
this.ucSplitLine_H1.TabIndex = ;
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(, , , );
this.Size = new System.Drawing.Size(, );
this.ResumeLayout(false); } #endregion private UCSplitLine_H ucSplitLine_H1;
private System.Windows.Forms.Label lblTitle;
}
}

设计效果如图

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

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

public UCHorizontalListItem SelectedItem { get; set; }
public event EventHandler SelectedItemEvent;
private int m_startItemIndex = ;
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 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 > )
this.panList.Width = panMain.Width + this.panList.Controls[].Location.X * -;
this.panList.Location = new Point(, );
m_startItemIndex = ;
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 > )
{
SelectItem((UCHorizontalListItem)this.panList.Controls[]);
}
}
finally
{
ControlHelper.FreezeControl(this, false);
}
}

还需要处理选中处理

  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 >= )
{
this.panList.Location = new Point(, );
return;
} for (int i = m_startItemIndex; i >= ; i--)
{
if (this.panList.Controls[i].Location.X < this.panList.Controls[m_startItemIndex].Location.X - panMain.Width)
{
m_startItemIndex = i + ;
break; ;
}
if (i == )
{
m_startItemIndex = ;
}
} ResetListLocation();
panRight.Visible = true;
if (this.panList.Location.X >= )
{
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 <= )
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 > )
{
this.panList.Location = new Point(this.panList.Controls[m_startItemIndex].Location.X * -, );
}
}

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

 public void SetSelect(string strKey)
{
foreach (UCHorizontalListItem item in this.panList.Controls)
{
if (item.DataSource.Key == strKey)
{
SelectItem(item);
return;
}
}
}

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

 // 版权所有  黄正辉  交流群:568015492   QQ:623128629
// 文件名称:UCHorizontalList.cs
// 创建日期:2019-08-15 16:01:06
// 功能描述:HorizontalList
// 项目地址:https://gitee.com/kwwwvagaa/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 = ;
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 > )
this.panList.Width = panMain.Width + this.panList.Controls[].Location.X * -;
this.panList.Location = new Point(, );
m_startItemIndex = ;
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 > )
{
SelectItem((UCHorizontalListItem)this.panList.Controls[]);
}
}
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 >= )
{
this.panList.Location = new Point(, );
return;
} for (int i = m_startItemIndex; i >= ; i--)
{
if (this.panList.Controls[i].Location.X < this.panList.Controls[m_startItemIndex].Location.X - panMain.Width)
{
m_startItemIndex = i + ;
break; ;
}
if (i == )
{
m_startItemIndex = ;
}
} ResetListLocation();
panRight.Visible = true;
if (this.panList.Location.X >= )
{
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 <= )
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 > )
{
this.panList.Location = new Point(this.panList.Controls[m_startItemIndex].Location.X * -, );
}
} 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>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null; /// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
} #region 组件设计器生成的代码 /// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </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(, );
this.panMain.Name = "panMain";
this.panMain.Size = new System.Drawing.Size(, );
this.panMain.TabIndex = ;
//
// panList
//
this.panList.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.panList.BackColor = System.Drawing.Color.Transparent;
this.panList.Location = new System.Drawing.Point(, );
this.panList.Name = "panList";
this.panList.Size = new System.Drawing.Size(, );
this.panList.TabIndex = ;
//
// 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(, );
this.panRight.Name = "panRight";
this.panRight.Size = new System.Drawing.Size(, );
this.panRight.TabIndex = ;
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(, );
this.panLeft.Name = "panLeft";
this.panLeft.Size = new System.Drawing.Size(, );
this.panLeft.TabIndex = ;
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(, );
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;
}
}

用处及效果

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

效果:

调用示例

  List<KeyValuePair<string, string>> lstHL = new List<KeyValuePair<string, string>>();
for (int i = ; i < ; i++)
{
lstHL.Add(new KeyValuePair<string, string>(i.ToString(), "选项" + i));
} this.ucHorizontalList1.DataSource = lstHL;

最后的话

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

(十)c#Winform自定义控件-横向列表的更多相关文章

  1. c#Winform自定义控件-目录

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  2. winform 自定义控件(高手)

    高手推荐:https://www.cnblogs.com/bfyx/p/11364884.html   c#Winform自定义控件-目录   前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件 ...

  3. (三十二)c#Winform自定义控件-表格

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  4. (七十九)c#Winform自定义控件-导航菜单

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  5. (八十二)c#Winform自定义控件-穿梭框

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  6. (三十)c#Winform自定义控件-文本框(三)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  7. (二十五)c#Winform自定义控件-有确定取消的窗体(一)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  8. (二十六)c#Winform自定义控件-有确定取消的窗体(二)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  9. (四十九)c#Winform自定义控件-下拉框(表格)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

随机推荐

  1. Unix及Linux编辑器vi/vim基本使用方法

  2. AWS S3 上传文件

    一.获取签名的URL 通过后端给的接口拿到已经签名好的文件上传的URL地址 二.读取文件(注:AWS 接受的二进制,不能使用form-data) // 获取文件二进制 getFileMd5 = (ke ...

  3. GPS常识-B版(简)

    第一章 绪论 1.简述GPS系统的特点有哪些? 在测绘工程中有如下优点:(1)定位精度高(2)观测时间短(3)测站间无需通视(4)可提供地心坐标(5)操作简便(6)全天候作业(7)功能多.应用广 GP ...

  4. ASP.NET--Web服务器端控件和Html控件

    今天学习总结了一些相关概念和知识. 之前无论是做 单机的winform 还是 CS的winform 感觉,不到两年下来感觉还可以,虽然API有很多,但是还是比较熟悉基于WINDOWS消息机制的编程,但 ...

  5. 创建 gif

    1.动态创建 <Container name="layLoading"/> if (m_pLoadingGif == NULL)  {   m_pLoadingGif ...

  6. [HAOI2006]聪明的猴子 题解

    题意: 在一个热带雨林中生存着一群猴子,它们以树上的果子为生.昨天下了一场大雨,现在雨过天晴,但整个雨林的地表还是被大水淹没着,部分植物的树冠露在水面上.猴子不会游泳,但跳跃能力比较强,它们仍然可以在 ...

  7. Python常用的标准库以及第三方库

    Python常用的标准库以及第三方库有哪些?   20个必不可少的Python库也是基本的第三方库 读者您好.今天我将介绍20个属于我常用工具的Python库,我相信你看完之后也会觉得离不开它们.他们 ...

  8. CSS画出三角形(利用Border)

    画出三角形的原理是调整border(边框)的四个方向的宽度,线条样式以及颜色. 如果你将宽度调的足够大,改变不同方向的颜色,你就可以发现盒模型的border是四个梯形一样的线条. div{ width ...

  9. MyEclipse2014破解版

    百度云:链接:http://pan.baidu.com/s/1c3jKMa 密码:yss0 等版本)后,不要打开软件. 二.解压破解文件压缩包,得到一下文件列表: 三.双击run.bat,即可运行cr ...

  10. Codeforces比赛注意事项(英语比较好,能翻译题目的可以跳过此文章)

    由题目可知,这篇文章是讲翻译文章的. 当然不是教英语啦 其实cf的比赛对于本蒟蒻最大的挑战就是翻译题目啦 所以我比赛时只能靠各种翻译器去无耻地翻译,然后读中文. 目前较好的翻译器有:百度,谷歌,有道. ...