如何用C#的DataGridView选择所有复选框?

问题描述 投票:0回答:2

我尝试选择所有复选框,但出现错误。

如果我在选中包含复选框的列时单击顶部的完整选中/释放复选框,则所选区域不会更改。

我该如何解决?

上图是点击完整版后的效果。

这是我的测试代码。

函数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;
            }
        }

    }
}
c# winforms datagridview
2个回答
1
投票

请考虑将数据绑定与您的

DataGridView
一起使用,这可以简化您想要做的事情。通过使用
Record
属性定义
bool IsChecked
类,当您将该记录添加到这些记录的绑定列表 of 时,会自动创建复选框行。然后,您可以通过在记录中设置属性来操作该检查,而不是对 UI 对象本身进行调用。

单击标题单元格:

  • 如果全部选中或取消选中,则全部都会切换。
  • 如果混合了已选中和未选中的内容,则所有内容都将提升为已选中。

这是 GitHub 上的工作示例。

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; }
    }
}

0
投票

如何制作一个函数或类来对我的所有项目数据网格视图使用此“全选复选框”? (我的项目中有20-30个dgv,我不想一一使用这些代码)

      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;

        }

    }
© www.soinside.com 2019 - 2024. All rights reserved.