重写DataGridViewColumn

做个项目需要用到DataGridView,这个控件还是挺好用的,但是今天却发现无法实现自己想要的功能。主要是DataGridViewCheckBoxColumn这个列虽然是提供了复选框,但是却未能在复选框的旁边提供文本的显示。在网上搜索了一下,提供的方法很多都是弄两列,然后合并单元格,将两列合并成为了一列。不过我不太喜欢那种方式,于是就自己重写了一下DataGridViewColumn,略显简陋,只实现了最基本的功能,现在拿出来,希望各位能够提一些好的意见和见解。

public class DataGridViewCheckBoxLabelColumn : DataGridViewColumn
    {
        public DataGridViewCheckBoxLabelColumn()
            : base()
        {
            CellTemplate = new DataGridViewCheckBoxCell();
        }

        /// <summary>
        /// 获取和设置用于创建新单元格的模板
        /// </summary>
        public override DataGridViewCell CellTemplate
        {
            get
            {
                return base.CellTemplate;
            }
            set
            {
                if (value != null && !value.GetType().IsAssignableFrom(typeof(DataGridViewCheckBoxCell)))
                {
                    throw new Exception("这个列里面必须绑定DataGridViewCheckBoxCell");
                }
                base.CellTemplate = value;
            }
        }

        protected override void OnDataGridViewChanged()
        {
            var dgv = this.DataGridView;
            int count = dgv.Rows.Count;
            for (int i = 0; i < count; i++)
            {
                if (dgv.Rows[i].Cells[Name] is DataGridViewCheckBoxCell)
                {
                    var cell = dgv.Rows[i].Cells[Name] as DataGridViewCheckBoxCell;
                    cell.Text = Text;
                }
            }
            base.OnDataGridViewChanged();
        }

        /// <summary>
        /// 复选框的文本
        /// </summary>
        public string Text { set; get; }

        public override object Clone()
        {
            DataGridViewCheckBoxLabelColumn col = (DataGridViewCheckBoxLabelColumn)base.Clone();
            col.Text = Text;
            return col;
        }

    }

    public class DataGridViewCheckBoxCell : DataGridViewCell
    {
        public DataGridViewCheckBoxCell() : base() { }
        /// <summary>
        /// 要显示的文本
        /// </summary>
        public string Text { set; get; }

        public override object Clone()
        {
            DataGridViewCheckBoxCell cell = (DataGridViewCheckBoxCell)base.Clone();
            cell.Text = Text;
            return cell;
        }

        /// <summary>
        /// 单元格的背景色
        /// </summary>
        private Color CellBackColor { get { return Selected ? Color.FromArgb(49, 106, 197) : OwningRow.DataGridView.BackgroundColor; } }
        /// <summary>
        /// 单元格前景色
        /// </summary>
        private Color CellForeColor { get { return Selected ? Color.White : OwningRow.DataGridView.ForeColor; } }
        /// <summary>
        /// 单元格边框颜色
        /// </summary>
        private Color CellBorderColor { get { return Color.FromArgb(172, 168, 153); } }
        /// <summary>
        /// 钩子的颜色
        /// </summary>
        private Color HookColor { get { return Color.FromArgb(33, 161, 33); } }
        /// <summary>
        /// 复选框边框颜色
        /// </summary>
        private Color CheckBoxBorderColor { get { return Color.FromArgb(28, 81, 128); } }

        public delegate void CheckedChangedHandle(object sender, DataGridViewCheckBoxLabelCheckedChangedEventArgs e);
        /// <summary>
        /// 单选框的选中状态发生变化时
        /// </summary>
        public event CheckedChangedHandle CheckedChanged;

        protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds,
            System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState,
            object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle,
            DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
            var cell = new Rectangle(cellBounds.X, cellBounds.Y, cellBounds.Width - 1, cellBounds.Height - 1);
            graphics.FillRectangle(new SolidBrush(CellBackColor), cell);
            graphics.DrawLine(new Pen(CellBorderColor), new Point(cell.X + cell.Width, cell.Y), new Point(cell.X + cell.Width, cell.Y + cell.Height));
            graphics.DrawLine(new Pen(CellBorderColor), new Point(cell.X, cell.Y + cell.Height), new Point(cell.X + cell.Width, cell.Y + cell.Height));
            var check = formattedValue.Equals("True") || formattedValue.Equals("true");
            var box = new Rectangle(cellBounds.X + 4, cellBounds.Y + (cellBounds.Height - 12) / 2, 12, 12);
            graphics.FillRectangle(new SolidBrush(Color.White), box);
            graphics.DrawRectangle(new Pen(CheckBoxBorderColor, 1.5f), box);
            if (check)
            {
                graphics.DrawString("", new Font("宋体", 8.0f, FontStyle.Bold), new SolidBrush(HookColor), new PointF(box.X - 2, box.Y + 2));
            }
            if (!string.IsNullOrEmpty(Text))
            {
                var s = graphics.MeasureString(Text, OwningRow.DataGridView.Font);
                var x = box.X + box.Width + 2;
                var y = cellBounds.Y + (cellBounds.Height - s.Height) / 2 + 1;
                graphics.DrawString(Text, OwningRow.DataGridView.Font, new SolidBrush(CellForeColor), new PointF(x, y));
            }
            base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);

        }

        protected override bool MouseClickUnsharesRow(DataGridViewCellMouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                var p = new Point(e.X, e.Y);
                var row = this.OwningRow;
                var x = 4;
                var y = (row.Height - 12) / 2;
                var r = new Rectangle(x, y, 12, 12);
                if (r.Contains(p))
                {
                    var check = FormattedValue.Equals("True") || FormattedValue.Equals("true");
                    Value = !check;
                    this.SetValue(RowIndex, Value);
                    if (CheckedChanged != null)
                        CheckedChanged(this, new DataGridViewCheckBoxLabelCheckedChangedEventArgs(!check, RowIndex, ColumnIndex));
                    RaiseCellValueChanged(new DataGridViewCellEventArgs(ColumnIndex, RowIndex));
                }
            }
            return base.MouseClickUnsharesRow(e);
        }
    }

    public class DataGridViewCheckBoxLabelCheckedChangedEventArgs : EventArgs
    {
        public DataGridViewCheckBoxLabelCheckedChangedEventArgs() : base() { }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="check">当前单选框是否被选中</param>
        /// <param name="rowIndex">单元格所在行的行号</param>
        /// <param name="columnIndex">单元格所在列的列号</param>
        public DataGridViewCheckBoxLabelCheckedChangedEventArgs(bool check, int rowIndex, int columnIndex)
            : base()
        {
            Checked = check;
            RowIndex = rowIndex;
            ColumnIndex = columnIndex;
        }
        /// <summary>
        /// 当前单选框是否被选中
        /// </summary>
        public bool Checked { set; get; }
        /// <summary>
        /// 单元格所在行的行号
        /// </summary>
        public int RowIndex { set; get; }
        /// <summary>
        /// 单元格所在列的列号
        /// </summary>
        public int ColumnIndex { set; get; }
    }

在使用了重写的列后,就基本实现了复选框的选中变化,并呈现了复选框旁边的文本,效果图如下:

重写DataGridViewColumn

重写DataGridViewColumn

上一篇:Retrofit 用Soap协议访问WebService 详解


下一篇:Windows7系统下ASP网站的发布