zoukankan      html  css  js  c++  java
  • 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;
    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";
            }

  • 相关阅读:
    POJ 基本算法(3)
    给定范围的素数筛选(POJ 2689)
    无向图、有向图的最小环
    第k短路和A*
    HDU 4302 Holedox Eating (set + iterator)
    笛卡尔树
    HDU 多校联合第一场
    HDU 多校联合第二场
    POJ 图算法(3)
    POJ 1038 Bugs Integrated, Inc. (状态dp)
  • 原文地址:https://www.cnblogs.com/ami/p/455360.html
Copyright © 2011-2022 走看看