.net WinForm使用者控制元件開發--(3)可多選的下拉列表框
先來看下效果圖吧,我會分幾個步驟來具體講解這個文字框的實現。
1.介面實現
我們先來看下介面效果怎樣實現,然後再講解具體的功能性實現。
先建立一個使用者控制元件,當然是繼承UserControl類,這個介面需要用到以下控制元件來實現
下拉按鈕:是一個button控制元件
文字框:顯示選中的內容,
多選列表框: checkboxlist
全選/取消:是兩個LABEL控制元件
右下角的黑三角:是一個LABEL控制元件,可實現拉長下拉列表框.
窗體:點選下拉按鈕,實際是彈出一個窗體,下拉列表框中的控制元件都在這個窗體中顯示
首先看下下拉按鈕的實現
/// <summary> /// 重寫BUTTON /// </summary> public class ButtonS : Button { public ButtonS() { //防止重繪控制元件出現閃爍 this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); } ButtonState state; //當按鈕被按下 protected override void OnMouseDown(MouseEventArgs mevent) { state = ButtonState.Pushed; base.OnMouseDown(mevent); } //當按鈕被釋放 protected override void OnMouseUp(MouseEventArgs mevent) { state = ButtonState.Normal; base.OnMouseUp(mevent); } protected override void OnPaint(PaintEventArgs pevent) { base.OnPaint(pevent); System.Windows.Forms.ControlPaint.DrawComboButton(pevent.Graphics, 0, 0, this.Width, this.Height, state); } }
接下來再看下具有拉動功能的LABEL
/// <summary> /// 重寫LABEL /// </summary> public class LabelS : Label { public LabelS() { //控制元件繪製的時候減少閃爍 this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); System.Windows.Forms.ControlPaint.DrawSizeGrip(e.Graphics, Color.Black, 1, 0, this.Size.Width, this.Size.Height); } }
接下來,我們動態用程式碼生成這些控制元件,並設定控制元件的佈局,
現在建構函式裡生成這些控制元件,然後在使用者控制元件的ComCheckBoxList_Layout事件裡面佈局這些控制元件,程式碼如下
/// <summary>
/// 帶下拉框的使用者控制元件
/// </summary>
public partial class ComCheckBoxList : UserControl
{
private TextBox tbSelectedValue;
private ButtonS btnSelect;//下拉箭頭
private LabelS lbGrip;//此LABEL用於設定可以拖動下拉窗體變化
private CheckedListBox checkListBox;
private Label lbSelectAll;//全選
private Label lbSelectNo;//取消
private Form frmCheckList;
private Panel pnlBack;
private Panel pnlCheck;
private System.Drawing.Point DragOffset; //用於記錄窗體大小變化的位置
public ComCheckBoxList()
{
InitializeComponent();
this.Name = "comBoxCheckBoxList";
this.Layout+=new LayoutEventHandler(ComCheckBoxList_Layout);
//生成控制元件
tbSelectedValue = new TextBox();
tbSelectedValue.ReadOnly = true;
tbSelectedValue.BorderStyle = BorderStyle.None;
//下拉箭頭
this.btnSelect = new ButtonS();
btnSelect.FlatStyle = FlatStyle.Flat;
btnSelect.Click+=new EventHandler(btnSelect_Click);
//全選
this.lbSelectAll = new Label();
lbSelectAll.BackColor = Color.Transparent;
lbSelectAll.Text = "全選";
lbSelectAll.Size = new Size(40, 20);
lbSelectAll.ForeColor = Color.Blue;
lbSelectAll.Cursor = Cursors.Hand ;
lbSelectAll.TextAlign = ContentAlignment.MiddleCenter;
lbSelectAll.Click+=new EventHandler(lbSelectAll_Click);
//取消
lbSelectNo = new Label();
lbSelectNo.BackColor = Color.Transparent;
lbSelectNo.Text = "取消";
lbSelectNo.Size = new Size(40, 20);
lbSelectNo.ForeColor = Color.Blue;
lbSelectNo.Cursor = Cursors.Hand;
lbSelectNo.TextAlign = ContentAlignment.MiddleCenter;
lbSelectNo.Click+=new EventHandler(lbSelectNo_Click);
//生成checkboxlist
this.checkListBox = new CheckedListBox();
checkListBox.BorderStyle = BorderStyle.None;
checkListBox.Location = new Point(0,0);
checkListBox.CheckOnClick = true;
checkListBox.ScrollAlwaysVisible = true;
checkListBox.LostFocus +=new EventHandler(checkListBox_LostFocus);
checkListBox.ItemCheck+=new ItemCheckEventHandler(checkListBox_ItemCheck);
//窗體
frmCheckList = new Form();
frmCheckList.FormBorderStyle = FormBorderStyle.None;
frmCheckList.StartPosition = FormStartPosition.Manual;
frmCheckList.BackColor = SystemColors.Control;
frmCheckList.ShowInTaskbar = false;
//可拖動窗體大小變化的LABEL
lbGrip = new LabelS();
lbGrip.Size = new Size(9,18);
lbGrip.BackColor = Color.Transparent;
lbGrip.Cursor = Cursors.SizeNWSE;
lbGrip.MouseDown+=new MouseEventHandler(lbGrip_MouseDown);
lbGrip.MouseMove+=new MouseEventHandler(lbGrip_MouseMove);
//panel
pnlBack = new Panel();
pnlBack.BorderStyle = BorderStyle.Fixed3D;
pnlBack.BackColor = Color.White;
pnlBack.AutoScroll = false;
//
pnlCheck = new Panel();
pnlCheck.BorderStyle = BorderStyle.FixedSingle;
pnlCheck.BackColor = Color.White; ;
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
pnlBack.Controls.Add(tbSelectedValue);
pnlBack.Controls.Add(btnSelect);
this.Controls.Add(pnlBack);
pnlCheck.Controls.Add(checkListBox);
pnlCheck.Controls.Add(lbSelectAll);
pnlCheck.Controls.Add(lbSelectNo);
pnlCheck.Controls.Add(lbGrip);
this.frmCheckList.Controls.Add(pnlCheck);
}
private void ReloationGrip()
{
lbGrip.Top = this.frmCheckList.Height - lbGrip.Height - 1;
lbGrip.Left = this.frmCheckList.Width - lbGrip.Width - 1;
lbSelectAll.Left =5;
lbSelectAll.Top = frmCheckList.Height - lbSelectAll.Height;
lbSelectNo.Left = 50;
lbSelectNo.Top = frmCheckList.Height - lbSelectNo.Height;
}
#region 事件
//佈局
private void ComCheckBoxList_Layout(object sender,LayoutEventArgs e)
{
this.Height = tbSelectedValue.Height + 6;
this.pnlBack.Size = new Size(this.Width, this.Height - 2);
//設定按鈕的位置
this.btnSelect.Size = new Size(16, this.Height - 6);
btnSelect.Location = new Point(this.Width - this.btnSelect.Width - 4, 0);
this.tbSelectedValue.Location = new Point(2, 2);
this.tbSelectedValue.Width = this.Width - btnSelect.Width - 4;
checkListBox.Height =150;
//設定窗體
this.frmCheckList.Size = new Size(this.Width,this.checkListBox.Height);
this.pnlCheck.Size =frmCheckList.Size;
this.checkListBox.Width = this.frmCheckList.Width;
this.checkListBox.Height = this.frmCheckList.Height-lbSelectNo.Height;
ReloationGrip();
}
/// <summary>
/// 單價下拉框
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void btnSelect_Click(object sender,EventArgs e)
{
if (this.frmCheckList.Visible == false)
{
Rectangle rec = this.RectangleToScreen(this.ClientRectangle);
this.frmCheckList.Location = new Point(rec.X, rec.Y + this.pnlBack.Height);
this.frmCheckList.Show();
this.frmCheckList.BringToFront();
ReloationGrip();
}
else
this.frmCheckList.Hide();
}
//全選事件
private void lbSelectAll_Click(object sender, EventArgs e)
{
}
//取消
private void lbSelectNo_Click(object sender,EventArgs e)
{
}
private void checkListBox_LostFocus(object sender, EventArgs e)
{
//如果滑鼠位置在下拉框按鈕的以為地方,則隱藏下拉框
if (!this.btnSelect.RectangleToScreen(this.btnSelect.ClientRectangle).Contains(Cursor.Position))
{
frmCheckList.Hide();
}
}
private void checkListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
}
/// <summary>
/// 滑鼠按下
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lbGrip_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button==MouseButtons.Left)
{
int offsetX = System.Math.Abs(Cursor.Position.X - frmCheckList.RectangleToScreen(this.frmCheckList.ClientRectangle).Right);
int offsetY = System.Math.Abs(Cursor.Position.Y - frmCheckList.RectangleToScreen(this.frmCheckList.ClientRectangle).Bottom);
this.DragOffset = new Point(offsetX, offsetY);
}
}
/// <summary>
/// 滑鼠移動
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lbGrip_MouseMove(object sender,MouseEventArgs e)
{
if (e.Button==MouseButtons.Left)
{
//獲取拉伸長度
int curWidth = Cursor.Position.X - frmCheckList.Location.X;
int curHeight = Cursor.Position.Y - frmCheckList.Location.Y;
if (curWidth<this.Width)
{
curWidth=this.Width;
}
if (curHeight<checkListBox.Height)
{
curHeight=checkListBox.Height;
}
this.frmCheckList.Size=new Size(this.Width,curHeight);
this.pnlCheck.Size=frmCheckList.Size;
this.checkListBox.Height=(this.frmCheckList.Height-lbGrip.Height)<50?50:this.frmCheckList.Height-lbGrip.Height;
ReloationGrip();
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
}
}
#endregion
}
這樣使用者控制元件的佈局以及完成,我們編譯專案,就可以拖動使用者控制元件到窗體上,看到效果了
2. 繫結和新增資料
2.1 從資料庫中讀取資料繫結顯示
既然可以從資料庫中讀取資料,資料來源就可以是DATATABLE,我們在這裡為使用者控制元件設定資料來源,以及繫結後,要顯示的欄位,以及對於的值欄位。
為控制元件新增以下屬性
/// <summary>
/// 設定資料來源
/// </summary>
public object DataSource
{
set
{
this.checkListBox.DataSource = value;
}
get
{
return checkListBox.DataSource;
}
}
/// <summary>
/// 設定值
/// </summary>
public string ValueMember
{
set
{
checkListBox.ValueMember = value;
}
}
/// <summary>
/// 設定顯示名稱
/// </summary>
public string DisplayMember
{
set
{
checkListBox.DisplayMember = value;
}
}
2.2 新增項
我們也可以不繫結資料來源,為控制元件新增項,所有這裡我們要為控制元件新增一個方法,可以實現手動新增項。
/// <summary>
/// 新增項
/// </summary>
public int AddItems(object value)
{
checkListBox.Items.Add(value);
return checkListBox.Items.Count;
}
這樣我們就為使用者控制元件實現了兩種顯示資料的方法。下面我們看看在窗體中怎樣使用這兩種方法
在窗體上放置兩個按鈕,然後繫結資料
private void button1_Click(object sender, EventArgs e)
{
//繫結資料來源
DataTable dt = new DataTable();
DataColumn dc1 = new DataColumn("weibo", typeof(System.String));
dt.Columns.Add(dc1);
DataColumn dc2 = new DataColumn("mail", typeof(System.String));
dt.Columns.Add(dc2);
DataColumn dc3 = new DataColumn("blog", typeof(System.String));
dt.Columns.Add(dc3);
for (int i = 0; i < 50; i++)
{
DataRow dr = dt.NewRow();
dr[0] = "下里巴人simple";
dr[1] = "[email protected]";
dr[2] = "msdn" + i.ToString();
dt.Rows.Add(dr);
}
comCheckBoxList1.DataSource = dt;
comCheckBoxList1.DisplayMember = "weibo";
comCheckBoxList1.ValueMember = "mail";
}
private void button2_Click(object sender, EventArgs e)
{
//新增項
comCheckBoxList2.AddItems("郵箱:[email protected]");
comCheckBoxList2.AddItems("微博:下里巴人simple");
}
至此,第二步驟已經完成,可以實現大部分功能了.
3.事件處理
這裡我們定義下全選事件,取消事件,和某項選中狀態更改時發生的事件
//全選事件
private void lbSelectAll_Click(object sender, EventArgs e)
{
for (int i = 0; i < checkListBox.Items.Count; i++)
{
checkListBox.SetItemChecked(i, true);
}
tbSelectedValue.Text ="已選擇"+checkListBox.Items.Count.ToString()+"項";
}
//取消
private void lbSelectNo_Click(object sender,EventArgs e)
{
for (int i = 0; i < checkListBox.Items.Count; i++)
{
checkListBox.SetItemChecked(i, false);
}
tbSelectedValue.Text = "沒有選擇!";
}
這裡我們自定義一個選項狀態更改時發生的事件,供別人使用的時候自行處理選擇狀態更改邏輯,需要我們自定義事件
//單擊列表項狀態更改事件
public delegate void CheckBoxListItemClick(object sender, ItemCheckEventArgs e);
public event CheckBoxListItemClick ItemClick;
private void checkListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
ItemClick(sender, e);
//獲取選中的數量
int nCount = this.checkListBox.CheckedItems.Count;
if (this.checkListBox.CheckedItems.Contains(this.checkListBox.Items[e.Index]))
{
if (e.NewValue != CheckState.Checked)
{
nCount--;
}
}
else
{
if (e.NewValue == CheckState.Checked)
{
nCount++;
}
}
tbSelectedValue.Text = "已選擇" + nCount.ToString() + "項";
}
/// <summary>
/// 選項集合
/// </summary>
public CheckedListBox.ObjectCollection Items
{
get
{
return checkListBox.Items;
}
}
/// <summary>
/// 獲取選中項的文字
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public string GetItemText(object item)
{
return checkListBox.GetItemText(item);
}
然後當用戶把控制元件拖放到窗體上,我們就可以使用該事件了。
/// <summary>
/// 獲取選中項的文字
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void comCheckBoxList1_ItemClick(object sender, ItemCheckEventArgs e)
{
string text=comCheckBoxList1.GetItemText(comCheckBoxList1.Items[e.Index]);
MessageBox.Show(text);
}
到此,這個控制元件的基本功能已經實現完成。再看下效果圖
相關推薦
.net WinForm使用者控制元件開發--(3)可多選的下拉列表框
這一節給大家演示一個具有多選功能的下拉列表框,其實就是一個文字框和checkboxlist組合實現的使用者控制元件,換個角度來實現自定義控制元件。 先來看下效果圖吧,我會分幾個步驟來具體講解這個文字框的實現。
可搜尋多選下拉列表外掛
可搜尋多選下拉列表外掛 參考:http://blog.csdn.net/xb12369/article/details/50999265 <html> <head> <title>jQuery bootstrap-sele
DevExpress Winform通用控制元件開發總結
文件購買地址:https://item.taobao.com/item.htm?id=5694774231111、該文件是本人在運用DevExpress Winform從事開發工作中彙編整理2、該售價不僅包括文件的當前版本,凡購買者,該文件的所有後續版本更新都無償提供,不再另
.NET WINFORM 常用控制元件和開源庫使用網摘彙總
datagridview http://www.cnblogs.com/peterzb/archive/2009/05/29/1491891.html NPOI http://tonyqus.sinaapp.com/tutorial Winform 實現類似w
Android 開發:(十)初識ExpandableListView(可擴充套件的下拉列表元件)
隨便扯點兒 前幾天做iOS仿QQ,其中好友列表頁面就有下拉列表的功能,iOS做法應該比安卓稍微複雜一點,其中佈局以及一些實現方法(協議方法)都類似,不一樣的應該是動畫切換效果,安卓提供現成的元件,用原生的就可以實現。 iOS示例 http://blog.
Android自定義控制元件之仿汽車之家下拉重新整理
關於下拉重新整理的實現原理我在上篇文章Android自定義控制元件之仿美團下拉重新整理中已經詳細介紹過了,這篇文章主要介紹錶盤的動畫實現原理 汽車之家的下拉重新整理分為三個狀態: 第一個狀態為下拉重新整理狀態(pull to refresh),在這個狀
多選下拉控制元件multiselect使用小結
專案開發中,需要用到多選下拉列表外掛,由於專案前端框架採用了bootstrap,因此自然選擇了bootstrap的元件。經瞭解其有兩組外掛: 1、第一個元件是寫bootstrap table的主人公 wenzhixin 封裝的一個元件—— 筆者參考了“
angularjs 多選下拉框 控制元件angularjs ui-select2
angularjs ui-select2:http://jsfiddle.net/jLD42/4/(這個網站測試通過),網站內容如下:找了很多其他的網站都沒用,這個是測試通過的,需要匯入所需要的js檔案,需要的圖片: 這個如果控制元件寬度是比較窄的話
下拉列表框【安卓3】
pan activity border cin left 資源 pro 內容 1.0 Spinner(下拉列表框) 方法 描述 CharSequence getPrompt () 取得提示文字 void setPrompt(CharSeque
UI標籤庫專題十一 JEECG智慧開發平臺 DictSelect 資料字典下拉選擇框
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
可選擇和輸入的下拉列表框示例
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>可選擇和輸入的下拉列表框</title&
MVC身份驗證.MVC過濾器.MVC6關鍵字Task,Async.前端模擬表單驗證,提交.自定義匿名集合.Edge匯出到Excel.BootstrapTree樹狀選單的全選和反選.bootstrap可搜尋可多選可全選下拉框
在寫這篇部落格之前要嘮叨幾句.本人已從事開發四年有餘.從前兩年的熱情如火.到現在的麻木.總感覺要像上突破.卻又不敢輕舉妄動. 沒事就寫點基礎程式碼.指點下新人吧 1.MVC身份驗證. 有兩種方式.一個是傳統的所有控制器繼承自定義Control,然後再裡面用MVC的過濾器攔截.所以每次網站的後臺被訪問時.
可選擇也可以輸入的下拉列表框
<html><head><title>TW之執行程式碼外掛--Ayin增強版</title><style type="text/css">...div,span,p,td,font{...}{font-size:9pt;}</style>
jQuery.autocomplete 可輸入的下拉選擇框
1. jsp <table class="posttable"> <colgroup> <col style=
wpf控制元件開發基礎(3) -屬性系統(2)
原文: wpf控制元件開發基礎(3) -屬性系統(2) 上篇說明了屬性存在的一系列問題. 屬性預設值,可以保證屬性的有效性. 屬性驗證有效性,可以對輸入的屬性進行校驗 屬性強制回撥, 即不管屬性有無發生變化,都要做出通知. 屬性變更通知,當屬性發生變
wpf控制元件開發基礎(4) -屬性系統(3)
原文: wpf控制元件開發基礎(4) -屬性系統(3) 知識回顧 接上篇,上篇我們真正接觸到了依賴屬性的用法,以及依賴屬性的屬性元資料的用法,並且也實實在在地解決了之前第二篇提到的一系列問題.來回顧一下 屬性預設值 屬性變更通知 屬性強制回撥 本篇將繼續討論上一篇提到的問題,主題依然是
C#.net 地圖控制元件開發(十一) 地圖控制元件MapControl
地圖控制元件 地圖控制元件(MapControl)包含了地圖物件(Map),並在控制元件重繪時將繪圖的控制代碼傳遞給地圖物件,讓地圖物件可以繪製圖層集合。 地圖控制元件類 作用:主要用來繪製地圖。 類:提供地圖物件屬性,可以將使用者自
C#.net 地圖控制元件開發(八) 地圖要素Feature
地圖要素 地圖要素(Feature)是構成地圖圖層的最小單元,它包括地物的幾何形狀,符號和描述資訊。描述資訊可以做成資料表的形式儲存在圖層類中,符號也可以儲存在圖層類中作為預設的要素符號,但是為了在圖層中突出表示某個特殊的地物,所以在地圖要素中也增加了符號屬性。
淺談Winform控制元件開發(一):使用GDI+美化基礎視窗
寫在前面: 本系列隨筆將作為我對於winform控制元件開發的心得總結,方便對一些讀者在GDI+、winform等技術方面進行一個入門級的講解,拋磚引玉。 別問為什麼不用WPF,為什麼不用QT。問就是懶,不想學。 本專案所有程式碼均開源在https://github.com/muxiang/
基於Quartz.Net的任務管理平臺開發(3) —— 任務管理平臺
.cn utility tro 完成 get blog 工具 https http 有了之前對Quartz.Net的原理的理解和配置,現在需要實現對運行任務的監控和管理,完成了任務管理平臺的開發,相關代碼已經托管GitHub: https://github.com/Vice