我可是森森呢 2023-07-20 19:03 采纳率: 96.3%
浏览 29
已结题

C# DataGridView自定义列无法正常显示

因DataGridView的单元格需要显示复杂的内容,所以打算自己创建一个列继承DataGridViewColumn
再创建类继承DataGridViewCell,和IDataGridViewEditingControl。但是实际展示出来的效果,却是一片空白。
我给DataGridView设置双缓冲后,单元格变得一片漆黑
(图片仅为测试,到时候放的是自定义控件而不是CheckBox)

img

img


以下是完整代码

public class 自定义列 : DataGridViewColumn {

        public 自定义列() : base (new 自定义单元格()) { }

        /// <summary> 
        /// 获取或设置用于创建新单元格的模板。 
        /// </summary> 
        public override DataGridViewCell CellTemplate {
            get {
                return base.CellTemplate;
            }
            set {
                base.CellTemplate = value;
            }
        }

    }
    public class 自定义单元格 : DataGridViewCell {

        public 自定义单元格() : base() { }

        // <summary> 
        /// 初始化用于编辑单元格的控件。 
        /// </summary> 
        /// <param name="rowIndex">单元格所在位置的从零开始的行索引。</param> 
        /// <param name="initialFormattedValue">它表示在开始编辑时单元格显示的值。</param> 
        /// <param name="dataGridViewCellStyle">表示单元格样式的 System.Windows.Forms.DataGridViewCellStyle。</param> 
        public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) {


            自定义编辑控件 ctl = (自定义编辑控件)DataGridView.EditingControl;
            if (Value != null && Value != System.DBNull.Value) {
                ctl.Checked = (bool)Value;
            }
            //初始化之后设置编辑状态的值 
            base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);

        }
        /// <summary> 
        /// 获取单元格的寄宿编辑控件的类型。 
        /// </summary> 
        public override Type EditType {
            get {
                return typeof(自定义编辑控件);
            }
        }
        /// <summary> 
        /// 获取或设置单元格中值的数据类型。 
        /// </summary> 
        public override Type ValueType {
            get {
                return typeof(bool);
            }
        }
        /// <summary> 
        /// 获取新记录所在行中单元格的默认值。 
        /// </summary> 
        public override object DefaultNewRowValue {
            get {
                return false;
            }
        }

    }
    public class 自定义编辑控件 : CheckBox, IDataGridViewEditingControl {

        public CheckBox Box;
        public DataGridView 关联表格;
        public int 行下标;
        public bool 是否被更改;


        public 自定义编辑控件() {
            Box = this;

        }

        /// <summary> 
        /// 更改控件的用户界面 (UI),使之与指定单元格样式一致。 
        /// </summary> 
        /// <param name="dataGridViewCellStyle">要用作用户界面的模型的 System.Windows.Forms.DataGridViewCellStyle。</param> 
        public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle) {
            this.Font = dataGridViewCellStyle.Font;
            Box.ForeColor = dataGridViewCellStyle.ForeColor;
            Box.BackColor = dataGridViewCellStyle.BackColor;
        }


        /// <summary> 
        /// 确定指定的键是应由编辑控件处理的常规输入键,还是应由 System.Windows.Forms.DataGridView 处理的特殊键。 
        /// </summary> 
        /// <param name="key">一个 System.Windows.Forms.Keys,表示按下的键。</param> 
        /// <param name="dataGridViewWantsInputKey">当 System.Windows.Forms.DataGridView 要处理 keyData 中的 System.Windows.Forms.Keys时,则为 true;否则为 false。</param> 
        /// <returns>如果指定的键是应由编辑控件处理的常规输入键,则为 true;否则为 false。</returns> 
        public bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey) {
            switch (keyData & Keys.KeyCode)     //设置方向键等都不令其进入编辑状态
            {
                case Keys.Left:
                case Keys.Up:
                case Keys.Down:
                case Keys.Right:
                case Keys.Home:
                case Keys.End:
                case Keys.PageDown:
                case Keys.PageUp:
                    return true;
                default:
                    return false;
            }
        }

        /// <summary> 
        /// 检索单元格的格式化值。 
        /// </summary> 
        /// <param name="context">System.Windows.Forms.DataGridViewDataErrorContexts 值的按位组合,它指定需要数据的上下文。</param> 
        /// <returns>一个 System.Object,表示单元格内容的格式化版本。</returns> 
        public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context) {
            return EditingControlFormattedValue;
        }

        /// <summary> 
        /// 准备当前选中的单元格以进行编辑。 
        /// </summary> 
        /// <param name="selectAll">为 true,则选择单元格的全部内容;否则为 false。</param> 
        public void PrepareEditingControlForEdit(bool selectAll) {

        }

        /// <summary> 
        /// 获取或设置包含单元格的 System.Windows.Forms.DataGridView。 
        /// </summary> 
        public DataGridView EditingControlDataGridView {
            get {
                return 关联表格;
            }
            set {
                关联表格 = value;
            }
        }

        /// <summary> 
        /// 默认格式化值
        /// 实现接口 IDataGridViewEditingControl.EditingControlFormattedValue  
        /// </summary> 
        public object EditingControlFormattedValue {
            get { return Box.Checked; }
            set { Box.Checked = (bool)value; }
        }

        /// <summary> 
        /// 获取或设置该承载单元格的父行的索引。包含该单元格的行的索引,如果没有父行,则为 -1。 
        /// </summary> 
        public int EditingControlRowIndex {
            get {
                return 行下标;
            }
            set {
                行下标 = value;
            }
        }


        /// <summary> 
        /// 获取或设置一个值,该值指示编辑控件的值是否与承载单元格的值不同。 
        /// </summary> 
        public bool EditingControlValueChanged {
            get {
                return 是否被更改;
            }
            set {
                是否被更改 = value;
            }
        }

        /// <summary> 
        /// 获取当鼠标指针位于 System.Windows.Forms.DataGridView.EditingPanel 上方但不位于编辑控件上方时所使用的光标。 
        /// </summary> 
        public Cursor EditingPanelCursor {
            get {
                return base.Cursor;
            }
        }

        /// <summary> 
        /// 获取或设置一个值,该值指示每当值更改时,是否需要重新定位单元格的内容。 
        /// </summary> 
        public bool RepositionEditingControlOnValueChange {
            get {
                return false;
            }
        }

        /// <summary>
        /// 值修改时通知datagridviewCell.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void uiSwitch_ActiveChanged(object sender, EventArgs e) {
            //DataGridView中Cell的Changed事件  
            EditingControlDataGridView.NotifyCurrentCellDirty(true);
        }
    }

Form窗体里:创建一个表格设置好列

        public Form1() {
            InitializeComponent();
            //给表格设置双缓冲,发现变黑色
            Type dgvType = this.dataGridView1.GetType();
            PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
            pi.SetValue(this.dataGridView1, true, null);
        }

        private void WinForm_Load(object sender, EventArgs e) {
            DataTable dt = new DataTable();
            dt.Columns.Add("名称");
            dt.Columns.Add("布尔");
            DataRow dr1 = dt.NewRow();
            dr1[0] = "测试1";
            dr1[1] = true;
            dt.Rows.Add(dr1);
            dataGridView1.DataSource = dt;
        }

        private void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e) {

        }

Form的设计器代码

        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing) {
            if (disposing && (components != null)) {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent() {
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
            this.Column2 = new TestForm.自定义列();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            this.SuspendLayout();
            // 
            // dataGridView1
            // 
            this.dataGridView1.AllowUserToAddRows = false;
            this.dataGridView1.AllowUserToDeleteRows = false;
            this.dataGridView1.AllowUserToResizeColumns = false;
            this.dataGridView1.AllowUserToResizeRows = false;
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
            this.Column1,
            this.Column2});
            this.dataGridView1.Location = new System.Drawing.Point(78, 176);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.RowTemplate.Height = 23;
            this.dataGridView1.Size = new System.Drawing.Size(434, 246);
            this.dataGridView1.TabIndex = 0;
            this.dataGridView1.DataError += new System.Windows.Forms.DataGridViewDataErrorEventHandler(this.dataGridView1_DataError);
            // 
            // Column1
            // 
            this.Column1.DataPropertyName = "名称";
            this.Column1.HeaderText = "名称";
            this.Column1.Name = "Column1";
            // 
            // Column2
            // 
            this.Column2.DataPropertyName = "布尔";
            this.Column2.HeaderText = "布尔";
            this.Column2.Name = "Column2";
            // 
            // WinForm
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Controls.Add(this.dataGridView1);
            this.Name = "WinForm";
            this.Text = "Form1";
            this.Load += new System.EventHandler(this.WinForm_Load);
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            this.ResumeLayout(false);

        }

        #endregion
        private System.Windows.Forms.DataGridView dataGridView1;
        private System.Windows.Forms.DataGridViewTextBoxColumn Column1;
        private 自定义列 Column2;

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-07-20 21:51
    关注
    • 你可以看下这个问题的回答https://ask.csdn.net/questions/260915
    • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:C#winform的datagridview去除列标头自带的排序,去除初始选中状态,添加自定义checkbox
    • 除此之外, 这篇博客: 关于Winform中DatagridView 表头checkBox全选选项框总结中的 表头CheckBox 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
    • 已办做C/S端,和前端有关系的你就避免不了做表格,避免不了使用DatagridView 。如果没什么特别要求,也就绑定下数据就行了:this.dataGridView1.DataSource=???具体的百度一下,这个还是有的。
      然而,如果只是查看这就解决了,但是有时需要都数据进行修改,删除,这些需要选择表格内容的操作,就需要多一步操作,如果只是单选也不用那麽复杂,但是既然选择了,肯定会考虑到多选,尽然考虑到多选,就肯定考虑到全选,所以。。。要么不做,要么做全。
      在这里插入图片描述在这里插入图片描述

      如图,Datagridview 自带DataGridViewCheckBoxColumn 将需要选择的行设置成这个属性,会自动生成多选项选择框。这一步很简单。
      关键是啊表头如何设置成这个多选框。
      在这里插入图片描述
      这个小方框的制作需要考虑;方案有两个:

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 7月30日
  • 已采纳回答 7月22日
  • 创建了问题 7月20日

悬赏问题

  • ¥20 模型在y分布之外的数据上预测能力不好如何解决
  • ¥15 processing提取音乐节奏
  • ¥15 gg加速器加速游戏时,提示不是x86架构
  • ¥15 python按要求编写程序
  • ¥15 Python输入字符串转化为列表排序具体见图,严格按照输入
  • ¥20 XP系统在重新启动后进不去桌面,一直黑屏。
  • ¥15 opencv图像处理,需要四个处理结果图
  • ¥15 无线移动边缘计算系统中的系统模型
  • ¥15 深度学习中的画图问题
  • ¥15 java报错:使用mybatis plus查询一个只返回一条数据的sql,却报错返回了1000多条