DataGridComboBoxColumn控件
Datagrid是由多个表(table)组成的,table是由行(row)与列(column)组成的,行与列的交互,组成的一个个单元(cell)。我们的需要就是能控制每一个cell的变化,从而使row与column发生变化,最终形成table的变化。这每一种变化都可视为是Datagrid中table的一种风格格式(style)。
我们在往form上部署Datagrid控件后,会在其属性窗口下方会出现“自动套用格式”,它们的变化多是背景色(Backcolor)与前景色(Forecolor)与字体(Font)的变化。经过本文的讲述后,您将能够实现更多的格式变化。
平常所看到的默认结构Datagrid,即把DatagridColumnStyle设定为DatagridTextBoxColumn列结构,把datagrid的列设为由textbox组成。从而我们就可以看到的那种效果就是每一个cell里都是一个textbox。同理,我们就知道如果把某一列的DatagridColumnStyle设定为DatagridBoolColumn列结构,就可以在该列中用checkbox控件显示与更改boolean类型的值了。我们甚至可以自定义某一列的列类型,加入combox等等.。
要实现创建一个列类,应该很好地再次研究一下DataGridTextBoxColumn类,并据此相似的创建一个新类,本次示例是要创建一个具有下拉框的列,因此,它应该与DataGridTextBoxColumn类是同级的,也就是说它们应该是从同个父类派生出来的,这样才可以在保证在使用上的相似性与一致性。
我们可以方便的了解到下拉框列的处理过程,在平常状况下,colboBox列中的cell还是以textbox的形式进行显示的,下拉框的出现是被textbox中落入焦点才激发的,而后,该cell就是一个实实在在的下拉框了,当焦点离开该cell后,cell又恢复成一个textbox的模样了。
正式要开工了,先理一下思路,我们要做些什么事:
(1) 从DataGridTextBoxColumn类的父类DataGridColumnStyle继承一个自定义列类:DataGridComboBoxColumn;
(2) 在列中加入一个ComboBox实例,用于聚焦后的出现,与DataGridTextBoxColumn类使用的textbox所属的DataGridTextBox类相似的,我们应该设计一个专用的combobox类提供给DataGridComboBoxColumn类使用。
(3) 跟踪cell的状态,当聚焦时在textbox的外面添加一个combobox,失去焦点后隐藏起combobox,恢复成textbox模样;
(4) 重写父类的Edit与Paint方法,以适应Combobox的使用,在Edit中将Combobox中产生的(用户输入或在下拉框中选择)变化记录入cell中,这也便于在更改后更新到相关的数据源中去。
现在来了解一下DataGridComboBox的运行机制。当第一次加载数据的时候,comboBox根据ValueMember绑定vaule,DisplayMember则绑定为text显示给大家看。ComboBoxColumn的显示则通过DataGrid的source和rowNum来决定,也就是将cell中的内容通过GetComboBoxText进行转换然后paint显示。为什么只需要source和rowNum来决定呢?那是因为DataGrid能够自动记录列号。
代码如下:
DataGridComboBox.cs
程序代码: | [ 复制代码 ] [ 运行代码 ] |
using System.Windows.Forms;
namespace DataGridComboBoxColumn
{
/// <summary>
/// DataGridComboBox 的摘要说明。
/// </summary>
public class DataGridComboBox:ComboBox
{
private const int WM_KEYUP = 0x101;
protected override void WndProc(ref System.Windows.Forms.Message message)
{
if (message.Msg == WM_KEYUP)
{
return;
}
base.WndProc(ref message);
}
//通过索引取得items的value。
public string GetValueText(int index)
{
if(index < 0 || index >= base.Items.Count)
{
//抛出索引超出异常
throw new IndexOutOfRangeException("无效索引。");
}
else
{
string text = string.Empty;
int memIndex = -1;
try
{
base.BeginUpdate();
memIndex = base.SelectedIndex;
base.SelectedIndex = index;
text = base.SelectedValue.ToString();
base.SelectedIndex = memIndex;
}
catch
{}
finally
{
base.EndUpdate();
}
return text;
}
}
//通过索引取得items的text
public string GetDisplayText(int index)
{
if(index <0 || index >=base.Items.Count)
{
//抛出索引超出异常
throw new IndexOutOfRangeException("无效索引。");
}
else
{
string text = string.Empty;
int memIndex = -1;
try
{
base.BeginUpdate();
memIndex = base.SelectedIndex;
base.SelectedIndex = index;
text = base.Text.ToString();
base.SelectedIndex = memIndex;
}
catch
{}
finally
{
base.EndUpdate();
}
return text;
}
}
//通过value取得items的text
public string GetDisplayText(object value)
{
string text = string.Empty;
int memIndex= -1;
try
{
base.BeginUpdate();
memIndex = base.SelectedIndex;
base.SelectedValue = value.ToString();
text = base.Text.ToString();
base.SelectedIndex = memIndex;
}
catch
{}
finally
{
base.EndUpdate();
}
return text;
}
//循环获取items的text
public string[] GetDisplayText()
{
string[] text = new string[base.Items.Count];
int memIndex = -1;
try
{
base.BeginUpdate();
memIndex = base.SelectedIndex;
for(int i=0;i<base.Items.Count;i++)
{
base.SelectedIndex = i;
text[i] = base.Text.ToString();
}
base.SelectedIndex = memIndex;
}
catch
{}
finally
{
base.EndUpdate();
}
return text;
}
}
}
DataGridComboBoxColumn.cs
程序代码: | [ 复制代码 ] [ 运行代码 ] |
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace DataGridComboBoxColumn
{
/// <summary>
/// DataGridComboBoxColumn 的摘要说明。
/// </summary>
public class DataGridComboBoxColumn : DataGridColumnStyle
{
private DataGridComboBox m_comboBox;
private bool m_edit;
public DataGridComboBoxColumn()
{
this.m_comboBox = new DataGridComboBox();
this.m_comboBox.Visible = false;
this.m_comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
this.m_comboBox.Leave +=new EventHandler(m_comboBox_Leave);
this.m_comboBox.SelectionChangeCommitted +=new EventHandler(m_comboBox_SelectedIndexChanged);
this.m_edit = false;
}
public ComboBox comboBox
{
get
{
return m_comboBox;
}
}
//comboBox事件
//失去焦点后comboBox隐藏
private void m_comboBox_Leave(object sender,EventArgs e)
{
this.m_comboBox.Hide();
}
//选定项发生更改并提交更改通知用户开始编辑列
private void m_comboBox_SelectedIndexChanged(object sender,EventArgs e)
{
this.m_edit = true;
base.ColumnStartedEditing((Control)sender);
}
//重写DataGridColunmStyle
protected override void SetDataGridInColumn(DataGrid value)
{
//将comboBox加入到DataGrid控件集合中
//确保正确的DataGrid scrolling
value.Controls.Add(this.m_comboBox);
base.SetDataGridInColumn (value);
}
//当 DataGridColumnStyle 方法的 Commit 方法返回 false 时,Abort 方法被 DataGrid 使用。
//在这种情况下,列值滚动回原先的值。
//在返回之前,DataGridColumnStyle 必须结束所有编辑操作。使用 Abort 方法来实现该操作。
//System.Windows.Forms.DataGrid 控件的 EndEdit 方法间接调用 Abort(如果其 ShouldAbort 参数设置为 true)。
protected override void Abort(int rowNum)
{
this.m_edit=false;
Invalidate();
this.m_comboBox.Hide();
}
//准备单元格以便进行编辑。
protected override void Edit(CurrencyManager source, int rowNum, System.Drawing.Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible)
{
this.m_comboBox.Parent = this.DataGridTableStyle.DataGrid;
this.m_comboBox.Bounds = bounds;
this.m_comboBox.Size = new System.Drawing.Size(this.Width,this.comboBox.Height);
this.m_comboBox.SelectedValue = base.GetColumnValueAtRow(source,rowNum).ToString();
this.m_comboBox.Visible = (!readOnly) && cellIsVisible;
this.m_comboBox.BringToFront();
this.m_comboBox.Focus();
}
//如果编辑过程成功提交,则为 true;否则为 false。
protected override bool Commit(CurrencyManager dataSource, int rowNum)
{
if(this.m_edit==true)
{
this.m_edit = false;
//保存值
this.SetColumnValueAtRow(dataSource, rowNum, this.m_comboBox.SelectedValue);
}
return true;
}
//获取指定 CurrencyManager 中指定行内的值。
protected override object GetColumnValueAtRow(CurrencyManager source, int rowNum)
{
//return base.GetColumnValueAtRow (source, rowNum);
return this.m_comboBox.GetDisplayText(base.GetColumnValueAtRow(source,rowNum));
}
//用来自指定 CurrencyManager 的值设置指定行中的值。
protected override void SetColumnValueAtRow(CurrencyManager source, int rowNum, object value)
{
try
{
base.SetColumnValueAtRow (source, rowNum, value.ToString());
return;
}
catch
{}
//下面是另外一种方法,对于使用GUID全局唯一标识符有效
try
{
base.SetColumnValueAtRow (source, rowNum, new Guid(value.ToString()));
return;
}
catch
{}
}
protected override int GetMinimumHeight()
{
return this.m_comboBox.PreferredHeight+2;
}
//在派生类中被重写时,将获取自动调整列的大小所用的高度。
protected override int GetPreferredHeight(System.Drawing.Graphics g, object value)
{
return FontHeight + 2 ;
}
//在派生类中被重写时,将获取指定值的宽度和高度。
//在用户定位到使用 DataGridColumnStyle 的 DataGridTableStyle 时将使用该宽度和高度。
protected override System.Drawing.Size GetPreferredSize(System.Drawing.Graphics g, object value)
{
//return new System.Drawing.Size ();
int widths = 0;
SizeF strF = new SizeF(0,0);
foreach (string str in this.m_comboBox.GetDisplayText())
{
strF = g.MeasureString(str, base.DataGridTableStyle.DataGrid.Font);
if(strF.Width > widths)
{
widths = (int)Math.Ceiling(strF.Width);///
}
}
return new System.Drawing.Size (widths +25,this.m_comboBox.PreferredHeight+2);
}
//绘制具有指定 Graphics、Rectangle、CurrencyManager 和行号的 DataGridColumnStyle。
protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle bounds, CurrencyManager source, int rowNum)
{
//绘制具有指定 Graphics、Rectangle、CurrencyManager、行号和对齐方式的 DataGridColumnStyle。
Paint(g, bounds, source, rowNum, false);
}
//绘制具有指定 Graphics、Rectangle、CurrencyManager、行号、背景色、前景色和对齐方式的 DataGridColumnStyle。
protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle bounds, CurrencyManager source, int rowNum, bool alignToRight)
{
//string text = this.GetColumnValueAtRow(source,rowNum).ToString();
string text = GetColumnValueAtRow(source,rowNum).ToString();
Brush backBrush = new SolidBrush(base.DataGridTableStyle.BackColor);
Brush foreBrush = new SolidBrush(base.DataGridTableStyle.ForeColor);
Rectangle rect = bounds;
StringFormat format = new StringFormat();
// 单元格被选中
if (base.DataGridTableStyle.DataGrid.IsSelected(rowNum) == true)
{
backBrush = new SolidBrush(base.DataGridTableStyle.SelectionBackColor);
foreBrush = new SolidBrush(base.DataGridTableStyle.SelectionForeColor);
}
if (alignToRight == true)
{
format.FormatFlags = StringFormatFlags.DirectionRightToLeft;
}
switch (this.Alignment)
{
case HorizontalAlignment.Left:
format.Alignment = StringAlignment.Near;
break;
case HorizontalAlignment.Right:
format.Alignment = StringAlignment.Far;
break;
case HorizontalAlignment.Center:
format.Alignment = StringAlignment.Center;
break;
}
// Paint.
format.FormatFlags = StringFormatFlags.NoWrap;
g.FillRectangle(backBrush, rect);
rect.Offset(0, 0);
rect.Height = 0;
g.DrawString(text,this.DataGridTableStyle.DataGrid.Font, foreBrush, rect, format);
format.Dispose();
}
}
}
private void DispDgList()
程序代码: | [ 复制代码 ] [ 运行代码 ] |
{
//创建一个新的DataGrid表格样式
DataGridTableStyle ts = new DataGridTableStyle();
ts.MappingName = this.DsBook.Tables[0].TableName;
//创建一个ComboBox控件的列
DataGridComboBoxColumn.DataGridComboBoxColumn cboCol = null;
//创建一个textBox控件的列
DataGridTextBoxColumn txtCol= null;
//计算列数
int numCols=this.DsBook.Tables[0].Columns.Count;
for (int i=0;i<numCols;i++)
{
if(this.DsBook.Tables[0].Columns[i].ColumnName.Equals("studentid"))
{
cboCol = new DataGridComboBoxColumn.DataGridComboBoxColumn();
cboCol.comboBox.DataSource = this.DsStudent.Tables[0];
cboCol.comboBox.DisplayMember = "name";
cboCol.comboBox.ValueMember = "studentid";
cboCol.HeaderText = "student";
cboCol.MappingName = "studentid";
ts.GridColumnStyles.Add(cboCol);
}
else
{
txtCol = new DataGridTextBoxColumn();
txtCol.HeaderText = this.DsBook.Tables[0].Columns[i].ColumnName;
txtCol.MappingName = this.DsBook.Tables[0].Columns[i].ColumnName;
ts.GridColumnStyles.Add(txtCol);
}
}
this.dataGrid1.TableStyles.Clear();
this.dataGrid1.TableStyles.Add(ts);
this.dataGrid1.DataSource = this.DsBook.Tables[0];
this.dataGrid1.CaptionText = "book";
}
转载于:https://www.cnblogs.com/ami/archive/2006/07/20/455360.html
DataGridComboBoxColumn控件相关推荐
- wpf控件设计时支持(2)
原文:wpf控件设计时支持(2) 这篇介绍在wpf设计时集合项属性添加项的定义和自定义控件右键菜单的方法 集合项属性设计时支持 1.为集合属性设计器识别具体项类型 wpf设计器允许定义集合项的类型,如 ...
- WPF 4 DataGrid 控件(基本功能篇)
提到DataGrid 不管是网页还是应用程序开发都会频繁使用.通过它我们可以灵活的在行与列间显示各种数据.本篇将详细介绍WPF 4 中DataGrid 的相关功能. 自定义列 默认情况下,当我们为Da ...
- WPF 基本控件的介绍
1.Border 放到其他控件内部,给其他控件画边框,其他容器必须支持双标签. 2.Button 按钮,按钮用图片应该设置内容为Image,而不能设置BackGroud为Image,如果 只设置背景, ...
- 详解WPF 4 DataGrid控件的基本功能
分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 详解WPF 4 D ...
- C# WPF DataGrid控件的详细介绍和推荐一些样式设计
前面介绍过使用DataGrid简单绑定一个数据模型,接着介绍DataGrid的一些详细操作. 参考:C# WPF DataGrid的使用 定制DataGrid控件基本外观属性 RowBackgroun ...
- C#WPF 常用控件
一.常用控件 1.(1).Border(边框)放到其他控件内部,给其他控件画边框,其他容器必须支持双标签.(2).Background决定背景颜色,BorderBrush决定边框颜色,BorderTh ...
- WPF(5)WPF之DataGrid控件
系列文章目录 WPF(1)WPF工程创建 WPF(2)WPF之Image组件 WPF(3)WPF之Button组件 文章目录 系列文章目录 前言 一.DataGrid入门? 1.1 CanUserAd ...
- WPF之DataGrid控件使用
WPF之DataGrid控件使用 一.DataGrid简介 二.DataGrid数据源绑定 三.DataGrid单元格编辑触发事件 四.DataGrid增加删除行 五.DataGrid数据触发器 参考 ...
- 2021-08-20 WPF控件专题 DataGrid控件详解
1.DataGrid控件介绍 DataGrid简介 :MultiSelector Selector ItemsControl -条目控件 网格控件:可以自定义网格显示的数据的控件 自定义网格:列的形式 ...
最新文章
- Spring点滴一:Spring Ioc 容器
- char 转为 int 类型
- VTK:PolyData之MergePoints
- mysql 随机查询数据
- Zookeeper已经设置了myid文件但是依然报错myid file is missing
- 中国科学院计算机网络信息中心领导,中国科学院计算机网络信息中心
- 统计学基础学习笔记:正态分布
- 【异常(待解决)】org.apache.http.NoHttpResponseException: api.weixin.qq.com:443 failed to respond
- python django步骤_python - django (ORM使用步骤)
- LanguageTool精简的两个思路
- 观察者模式在制作披萨项目中的应用
- 空格、句读、标点:从近代报刊到现代汉字标点符号萌芽与发展的考据
- autojs之百度地图定位
- 税务会计实务【18】
- 7-1 输出n个数 (10 分)
- 如何判断vps的好坏?
- PIE-engine APP 教程 ——太湖生态环境智能监测系统
- DeFi守护神是谁?
- 虚拟串口VSPD和XCOM的下载+安装+使用
- 【数字电路基础】CMOS晶体管的延时
热门文章
- 大学生计算机社团该办什么活动,大学生社团活动策划方案
- java包裹邮费计算_GitHub - honghailiang/FreightSystem: 基于Java Swing编写的简易运费计算工具...
- java 调用groovy_Java调用Groovy脚本
- pandas python groupby_python – 如何使用pandas groupby汇总多个列?
- java控制关键字continue,break,return
- android 邮件分享链接,Android应用从通过电子邮件发送的链接打开
- rstudio的数据集怎么建立和保存_这个40M的小工具助你在windows下处理数据如虎添翼...
- C语言fscanf和fprintf函数的用法详解
- 高中关于人工智能方面的课题_2019山东人工智能教育专项课题指南选题
- c++实现卷积码编码和维特比译码_鑫艾勒维特家用别墅电梯:安全至上,无可替代...