ComboBox控件很好用,但有时希望其下拉的数据更丰富一些,不要那么单调,后来自己琢磨一下,看看能不能自定义一个,经过查找网上资料加自己整理,做出一个demo,很糙,请随便拍!
【版本信息】:Microsoft Visual Studio 2010 Ultimate(旗舰版) 版本 10.0.40219.1 SP1Rel
Microsoft .NET Framework 版本 4.0.30319 SP1Rel
废话不多话,先看效果。
【全部代码在最下方】
具体实现如下:
第一部分:控件的自定义
控件的外观实现部分:由低到高分为4层。最底下一层为ToolStripDropDown,即点击ComboBox右侧的小黑三角后呈现的这部分,最底下一层ToolStripDropDown命名为(dropDown)。第二层为两块ToolStripControlHost,其目的是盛放TextBox和DataGridView,因此两部分自定义名称textBoxHost、dataGridViewHost。第三层有两块:TextBox和Form。如下图中的③、④所示。 第四层为DataGridView,如5所示。
声明部分的代码如下:
ToolStripControlHost dataGridViewHost; //声明盛放DataGridView的ToolStripControlHost ToolStripControlHost textBoxHost; //声明盛放TextBox的ToolStripControlHost ToolStripDropDown dropDown; //声明dropDown DataGridView dataGridView = new DataGridView(); //声明DataGridView dataGridView.BorderStyle = BorderStyle.FixedSingle; dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect; dataGridView.AllowUserToAddRows = false; dataGridView.AllowUserToDeleteRows = false; dataGridView.DoubleClick+=new EventHandler(dataGridView_DoubleClick); Form frmDataSource = new Form(); //声明Form frmDataSource.Controls.Add(dataGridView); TextBox testBox = new TextBox(); testBox.KeyPress += new KeyPressEventHandler(testBox_KeyPress); testBox.TextChanged += new EventHandler(testBox_TextChanged); textBoxHost = new ToolStripControlHost(testBox); textBoxHost.AutoSize = true; dataGridViewHost = new ToolStripControlHost(dataGridView); dropDown = new ToolStripDropDown(); dropDown.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow; dropDown.Items.Add(textBoxHost); dropDown.Items.Add(dataGridViewHost);
代码添加完成后,则需要添加各种事件:
添加的事件及完整代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Security.Permissions; using System.Drawing; using System.Data; namespace MyDataGridViewPlugin { [SecurityPermissionAttribute(SecurityAction.LinkDemand,Flags=SecurityPermissionFlag.UnmanagedCode)] class DataViewPlugin : ComboBox { ToolStripControlHost dataGridViewHost; ToolStripControlHost textBoxHost; ToolStripDropDown dropDown; public DataViewPlugin() { // DataGridView dataGridView = new DataGridView(); dataGridView.BorderStyle = BorderStyle.FixedSingle; dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect; dataGridView.AllowUserToAddRows = false; dataGridView.AllowUserToDeleteRows = false; dataGridView.DoubleClick+=new EventHandler(dataGridView_DoubleClick); Form frmDataSource = new Form(); frmDataSource.Controls.Add(dataGridView); TextBox testBox = new TextBox(); testBox.KeyPress += new KeyPressEventHandler(testBox_KeyPress); testBox.TextChanged += new EventHandler(testBox_TextChanged); textBoxHost = new ToolStripControlHost(testBox); textBoxHost.AutoSize = true; dataGridViewHost = new ToolStripControlHost(dataGridView); dropDown = new ToolStripDropDown(); dropDown.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow; dropDown.Items.Add(textBoxHost); dropDown.Items.Add(dataGridViewHost); } //文本框输入内容时,ComboBox置空 void testBox_TextChanged(object sender, EventArgs e) { base.Text = ""; } //文本框输入欲查询的值,监听回车事件 void testBox_KeyPress(object sender, KeyPressEventArgs e) { if((int)e.KeyChar==13) //监听 回车事件 { for (int i = 0; i < DataGridView.RowCount; i++) { if (TextBox.Text.ToString().Trim() == DataGridView[0, i].Value.ToString().Trim())//此处的 { DataGridView.CurrentCell=DataGridView[0,i]; return; } } MessageBox.Show("未找到以下指定文本:\n\n" + TextBox.Text.ToString().Trim(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); } } //DataGridView双击返填回ComboBox void dataGridView_DoubleClick(object sender, EventArgs e) { PopupGridView(); } private void PopupGridView() { DataGridViewRow currentRow = DataGridView.CurrentRow; base.Text = currentRow.Cells[0].Value.ToString(); base.Refresh(); TextBox.Text = ""; } public DataGridView DataGridView { get { return dataGridViewHost.Control as DataGridView; } } public TextBox TextBox { get { return textBoxHost.Control as TextBox; } } //点击ComboBox右侧小黑三角后,出现的下拉框 public void ShowDropDown() { if(dropDown!=null) { dataGridViewHost.Height = DropDownHeight; dataGridViewHost.Width = DropDownWidth; dropDown.Show(this, 0, this.Height); } } //下面的部分主要是处理消息,有兴趣的可以参考MSDN上关于message及message queue。具体点击这儿 //若不感兴趣,可以直接复制粘贴。学过C++的会感到比较easy private const int WM_USER = 0x0400, WM_REFLECT = WM_USER + 0x1c00, //自定义事件 WM_COMMAND = 0x0111, CBN_DROPDOWN = 7; //取高位值 public static int HIWORD(int n) { return (n >> 16) & 0xffff; } int i = 0; //重写消息处理方法 protected override void WndProc(ref Message m) { if (m.Msg == (WM_REFLECT + WM_COMMAND)) { if (HIWORD((int)m.WParam) == CBN_DROPDOWN) { ShowDropDown(); return; } } base.WndProc(ref m); i++; } protected override void Dispose(bool disposing) { if (disposing) { if (dropDown != null) { dropDown.Dispose(); dropDown = null; } } base.Dispose(disposing); } } }
以上就是自定义的控件的实现。
具体使用如下:
public partial class Form1 : Form { public Form1() { InitializeComponent(); this.Load += new EventHandler(Form1_Load); } void Form1_Load(object sender, EventArgs e) { //准备数据 DataTable myDataTable = new DataTable(); myDataTable.Columns.Add("姓名",typeof(System.String)); myDataTable.Columns.Add("年龄",typeof(System.String)); for (int i = 1; i <= 10; i++) { myDataTable.Rows.Add(new object[] { "张三_"+i, 6+i }); } //自定义控件赋值 myPlug.DataGridView.DataSource = myDataTable; this.Controls.Add(myPlug); } }
很简单。
有了自定控件之后,就可以随心所欲的添加到其他的控件中了。最近打算把这个自定义控件添加到DataGridView中,看看效果如何。
全部代码如下:
在这儿
ComboBox自定义实现(Realization of the DataGridView-plugin in ComboBox)