控件
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;
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;
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()

程序代码: [ 复制代码 ] [ 运行代码 ] 
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控件相关推荐

  1. wpf控件设计时支持(2)

    原文:wpf控件设计时支持(2) 这篇介绍在wpf设计时集合项属性添加项的定义和自定义控件右键菜单的方法 集合项属性设计时支持 1.为集合属性设计器识别具体项类型 wpf设计器允许定义集合项的类型,如 ...

  2. WPF 4 DataGrid 控件(基本功能篇)

    提到DataGrid 不管是网页还是应用程序开发都会频繁使用.通过它我们可以灵活的在行与列间显示各种数据.本篇将详细介绍WPF 4 中DataGrid 的相关功能. 自定义列 默认情况下,当我们为Da ...

  3. WPF 基本控件的介绍

    1.Border 放到其他控件内部,给其他控件画边框,其他容器必须支持双标签. 2.Button 按钮,按钮用图片应该设置内容为Image,而不能设置BackGroud为Image,如果 只设置背景, ...

  4. 详解WPF 4 DataGrid控件的基本功能

    分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 详解WPF 4 D ...

  5. C# WPF DataGrid控件的详细介绍和推荐一些样式设计

    前面介绍过使用DataGrid简单绑定一个数据模型,接着介绍DataGrid的一些详细操作. 参考:C# WPF DataGrid的使用 定制DataGrid控件基本外观属性 RowBackgroun ...

  6. C#WPF 常用控件

    一.常用控件 1.(1).Border(边框)放到其他控件内部,给其他控件画边框,其他容器必须支持双标签.(2).Background决定背景颜色,BorderBrush决定边框颜色,BorderTh ...

  7. WPF(5)WPF之DataGrid控件

    系列文章目录 WPF(1)WPF工程创建 WPF(2)WPF之Image组件 WPF(3)WPF之Button组件 文章目录 系列文章目录 前言 一.DataGrid入门? 1.1 CanUserAd ...

  8. WPF之DataGrid控件使用

    WPF之DataGrid控件使用 一.DataGrid简介 二.DataGrid数据源绑定 三.DataGrid单元格编辑触发事件 四.DataGrid增加删除行 五.DataGrid数据触发器 参考 ...

  9. 2021-08-20 WPF控件专题 DataGrid控件详解

    1.DataGrid控件介绍 DataGrid简介 :MultiSelector Selector ItemsControl -条目控件 网格控件:可以自定义网格显示的数据的控件 自定义网格:列的形式 ...

最新文章

  1. Spring点滴一:Spring Ioc 容器
  2. char 转为 int 类型
  3. VTK:PolyData之MergePoints
  4. mysql 随机查询数据
  5. Zookeeper已经设置了myid文件但是依然报错myid file is missing
  6. 中国科学院计算机网络信息中心领导,中国科学院计算机网络信息中心
  7. 统计学基础学习笔记:正态分布
  8. 【异常(待解决)】org.apache.http.NoHttpResponseException: api.weixin.qq.com:443 failed to respond
  9. python django步骤_python - django (ORM使用步骤)
  10. LanguageTool精简的两个思路
  11. 观察者模式在制作披萨项目中的应用
  12. 空格、句读、标点:从近代报刊到现代汉字标点符号萌芽与发展的考据
  13. autojs之百度地图定位
  14. 税务会计实务【18】
  15. 7-1 输出n个数 (10 分)
  16. 如何判断vps的好坏?
  17. PIE-engine APP 教程 ——太湖生态环境智能监测系统
  18. DeFi守护神是谁?
  19. 虚拟串口VSPD和XCOM的下载+安装+使用
  20. 【数字电路基础】CMOS晶体管的延时

热门文章

  1. 大学生计算机社团该办什么活动,大学生社团活动策划方案
  2. java包裹邮费计算_GitHub - honghailiang/FreightSystem: 基于Java Swing编写的简易运费计算工具...
  3. java 调用groovy_Java调用Groovy脚本
  4. pandas python groupby_python – 如何使用pandas groupby汇总多个列?
  5. java控制关键字continue,break,return
  6. android 邮件分享链接,Android应用从通过电子邮件发送的链接打开
  7. rstudio的数据集怎么建立和保存_这个40M的小工具助你在windows下处理数据如虎添翼...
  8. C语言fscanf和fprintf函数的用法详解
  9. 高中关于人工智能方面的课题_2019山东人工智能教育专项课题指南选题
  10. c++实现卷积码编码和维特比译码_鑫艾勒维特家用别墅电梯:安全至上,无可替代...