当前位置: 首页 > news >正文

C# DataGridView 选中所有复选框

问题描述 

        在程序中尝试选中所有复选框,但出现错误。如果单击顶部的完整选中/释放复选框,同时选中包含复选框的列,则选定区域不会改变。该如何解决?

上面的图片是点击完整版本之后的。

下面是本文的测试代码,函数 dataGridView1_CellPainting() 和 dgvCheckBox_CheckedChanged() 用于完整检查/释放操作。

namespace TestWinForm
{
    public partial class Form1 : Form
    {
        List<string> saved_file_names = new List<string>();
        int table_index = 0;

        public Form1()
        {
            InitializeComponent();
        }

        private void add_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "文本";
            ofd.Filter =  "txt | *.txt";
            ofd.Multiselect = true; // 

            DialogResult dr = ofd.ShowDialog();

            if (dr == DialogResult.OK)
            {
                foreach (string file_name in ofd.FileNames)
                {
                    //  1. 
                    if (saved_file_names.Contains(file_name))
                        continue;

                    //  2. 
                    dataGridView1.Rows.Add();
                    dataGridView1.Rows[table_index].Cells[1].Value = table_index + 1;
                    dataGridView1.Rows[table_index].Cells[2].Value = file_name;
                    saved_file_names.Add(file_name);
                    dataGridView1.Rows[table_index].Cells[3].Value = "none";
                    table_index++;
                }
            }
        }

        private void delete_Click(object sender, EventArgs e)
        {
            bool is_checked = false;
            List<int> delete_index = new List<int>();
            for (int i = 0; i < table_index; i++)
            {
                if (Convert.ToBoolean(dataGridView1.Rows[i].Cells[0].Value) == true)
                    delete_index.Add(i);
            }

            if (delete_index.Count == 0)
                return;

            delete_index.Reverse();

            foreach (var index in delete_index)
            {
                table_index--;
                saved_file_names.RemoveAt(index);
                dataGridView1.Rows.RemoveAt(index);
            }
        }

        private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (e.ColumnIndex == 0 && e.RowIndex == -1)
            {
                e.PaintBackground(e.ClipBounds, false);
                Point pt = e.CellBounds.Location;

                int nChkBoxWidth = 15;
                int nChkBoxHeight = 15;
                int offsetx = (e.CellBounds.Width - nChkBoxWidth) / 2;
                int offsety = (e.CellBounds.Height - nChkBoxHeight) / 2;

                pt.X += offsetx;
                pt.Y += offsety;

                CheckBox cb = new CheckBox();

                cb.Size = new Size(nChkBoxWidth, nChkBoxHeight);
                cb.Location = pt;
                cb.Checked = true;
                cb.CheckedChanged += new EventHandler(dgvCheckBox_CheckedChanged);

                ((DataGridView)sender).Controls.Add(cb);

                e.Handled = true;

            }

        }

        private void dgvCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            foreach (DataGridViewRow r in dataGridView1.Rows)
            {
                r.Cells[0].Value = ((CheckBox)sender).Checked;
            }
        }

    }
}

解决方法

        请考虑使用数据绑定,DataGridView这可以简化您的操作。通过定义一个Record包含属性的类,当您将该记录添加到这些记录的bool IsChecked绑定列表时,复选框行会自动创建。然后,您可以通过在记录中设置属性来操作该复选框,而无需调用 UI 对象本身。

单击标题单元格:

        如果全部选中或未选中,则全部将切换。

        如果混合了已选中和未选中,则所有都将被提升为已选中。

示例代码:

using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;

namespace dgv_ac
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Wait for the main form to be created, then attach 
        /// your Binding List as the data source of the DGV
        /// </summary>
        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            dataGridView1.DataSource = this.DataSource;
            initDGV();
        }

        private void initDGV()
        {
            dataGridView1.AllowUserToAddRows = false;

            // Now you can populate the DataGridView simply
            // by adding some records to the list.
            for (int i = 0; i < 5; i++)
            {
                DataSource.Add(new Record { Number = i, FileName = $"MyFile_{i}.txt" });
            }


            // Once the first record is added, the Columns information is
            // available and we can do column formatting.
            dataGridView1.Columns[nameof(Record.FileName)].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            var checkboxColumn = dataGridView1.Columns[nameof(Record.IsChecked)];
            checkboxColumn.HeaderText = string.Empty;
            checkboxColumn.Width = 40;
            dataGridView1.CellClick += onCellClick;
            dataGridView1.CellContentClick += onCellContentClick;
        }

        /// <summary>
        /// Detect check box click and end the edit mode in this case.
        /// </summary>
        private void onCellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if(e.RowIndex != -1)
            {
                var cell = dataGridView1[e.ColumnIndex, e.RowIndex];
                if(cell is DataGridViewCheckBoxCell checkbox)
                {
                    dataGridView1.EndEdit();
                }
            }
        }


        /// <summary>
        /// Detect header click and set the records accordingly.
        /// </summary>
        private void onCellClick(object sender, DataGridViewCellEventArgs e)
        {
            if(e.RowIndex == -1)
            {
                switch (dataGridView1.Columns[e.ColumnIndex].Name)
                {
                    case nameof(Record.IsChecked):
                        if (DataSource.Any())   // Check to see if there are any records at all.
                        {
                            if(DataSource.Count(record=>record.IsChecked) == DataSource.Count)
                            {
                                // This block says thet're all chacked or all unchecked.
                                if(DataSource.First().IsChecked) // then they all are
                                {
                                    setAll(false);
                                }
                                else
                                {
                                    setAll(true);
                                }
                            }
                            else setAll(true); // If they're mixed, make them all checked.
                        }
                        break;
                }
            }
            void setAll(bool value)
            {
                foreach (var record in DataSource)
                {
                    record.IsChecked = value;
                }
                Refresh();
            }
        }

        public BindingList<Record> DataSource = new BindingList<Record>();
    }

    
    // This is the record class that will provide column 
    // information to the DataGridView automatically.
    public class Record
    {
        public int Number { get; set; }
        public bool IsChecked { get; set; }
        public string FileName { get; set; }
    }
}

另一种方法

这种方式,本文未测试:

 private void dgvCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            foreach (DataGridViewRow r in dataGridView1.Rows)
            {
                if (r.Cells[0] is DataGridViewCheckBoxCell checkbox)
                {
                    dataGridViewDocuments.EndEdit();
                }
                r.Cells[0].Value = ((CheckBox)sender).Checked;
            }
        } 

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

相关文章:

  • Centos7系统(最小化安装)安装zabbix7版本详细文章、nginx源代码配置、php源代码、mysql-yum安装
  • CSS面试题汇总
  • 【Rust闭包】rust语言闭包函数原理用法汇总与应用实战
  • 微信小程序:封装表格组件并引用
  • C++之unordered_map/unordered_set模拟实现
  • conda创建环境常用命令(个人用)
  • STM32就业前景和下载KEIL软件(保姆级)
  • Vue3中setup运行时机介绍
  • FC7300 DMA MCAL 配置引导
  • 经典循环神经网络变体
  • 将已打包好的aar文件,上传到 Coding 的 Maven 仓库
  • Windows11安装rockerMq5.0+以及springboot集成rockerMq
  • iOS SwiftUI的具体运用实例(SwiftUI库的运用)
  • 大语言模型 10 - 从0开始训练GPT 0.25B参数量 补充知识之模型架构 MoE、ReLU、FFN、MixFFN
  • 应用层DDoS防护:从请求特征到行为链分析
  • Day 27 函数专题2 装饰器
  • 高可用消息队列实战:AWS SQS 在分布式系统中的核心解决方案
  • Core Web Vitals 全链路优化:从浏览器引擎到网络协议深度调优
  • Java + 鸿蒙双引擎:ZKmall开源商城如何定义下一代B2C商城技术标准?
  • 【Linux网络】数据链路层
  • 上海博物馆展览进校园,“小先生”传递文物知识
  • 试点首发进口消费品检验便利化措施,上海海关与上海商务委发文
  • 一图看懂|印巴交火后,双方基地受损多少?
  • 端午假期购票日历发布,今日可购买5月29日火车票
  • 美英贸易协议|不,这不是一份重大贸易协议
  • 为证明我爸是我爸,我将奶奶告上法庭