WinForms - DataGridViewCell未设置为只读

时间:2017-05-15 09:15:32

标签: c# .net winforms

我正在开发一个旧的.Net 2.0 WinForms项目,需要将一些单元格设置为只读。

我正在阅读DataTable并将其设置为DataSource并正确设置字段类型

生成DataTable和列

public DataTable FilterData(DataTable datatable, string dataType)
    {
        try
        {
            if (dataType == "MailPreferences")
            {

                var dt = new DataTable();

                dt.Columns.Add("SEQ_ID", typeof(int));                              // SEQ_ID
                dt.Columns.Add("MAIL_PREFERENCE_ID", typeof(string));               // MAIL_PREFERENCE_ID
                dt.Columns.Add("Mail Preference Description", typeof(string));      // MAIL_PREFERENCE_DESC
                dt.Columns.Add("Post", typeof(bool));                               // POST
                dt.Columns.Add("SMS", typeof(bool));                                // SMS
                dt.Columns.Add("Email", typeof(bool));                              // EMAIL
                dt.Columns.Add("Telephone", typeof(bool));                          // TELEPHONE

                foreach (DataRow row in datatable.Rows)
                {
                    dt.Rows.Add(row["SEQ_ID"].ToString(), 
                                row["MAIL_PREFERENCE_ID"].ToString(), 
                                row["MAIL_PREFERENCE_DESC"].ToString(),
                                Convert.ToBoolean(row["POST"]), 
                                Convert.ToBoolean(row["SMS"]), 
                                Convert.ToBoolean(row["EMAIL"]),
                                Convert.ToBoolean(row["TELEPHONE"]));
                }

                return dt;

            }


        }
        catch (Exception ex)
        {
            // catch and deal with my exception here
        }

        return null;
    }

这里正在调用上述方法,这就是我遇到禁用单元格的问题。

private void PopulateMailPreferencesGV()
    {
        var dt = FilterData(_cAddPersonWizard.GetMailPreferneces(), "MailPreferences");
        dgvMailPreferences.DataSource = dt;

        dgvMailPreferences.Columns["Mail Preference Description"].Width = 250;
        dgvMailPreferences.Columns["Post"].Width = 50;
        dgvMailPreferences.Columns["SMS"].Width = 50;
        dgvMailPreferences.Columns["Email"].Width = 50;
        dgvMailPreferences.Columns["Telephone"].Width = 75;

        dgvMailPreferences.Columns["SEQ_ID"].Visible = false;
        dgvMailPreferences.Columns["MAIL_PREFERENCE_ID"].Visible = false;


        // not setting the datagridview cell to readonly
        foreach (DataGridViewRow row in dgvMailPreferences.Rows)
        {
            foreach (DataGridViewCell cell in row.Cells)
            {
                if (cell.GetType() == typeof(DataGridViewCheckBoxCell))
                {
                    if(((DataGridViewCheckBoxCell)row.Cells[cell.ColumnIndex]).Selected == false)
                    {
                        ((DataGridViewCheckBoxCell)row.Cells[cell.ColumnIndex]).ReadOnly = true;
                    }
                }
            }
        }

    }

当单步执行并查看Watch窗口时,我可以看到正在设置只读属性,但是当使用DataGridView时,单元格仍处于活动状态。

如果有人能指出我这个代码出错的地方或我是否需要做其他事情,我将不胜感激?

感谢您的帮助。

---编辑2017年5月31日

enter image description here

上图显示了我要使用的网格,默认情况下会选择所选的选项。

要禁用未选择的选项,因为邮件类型

无法使用这些传送形式

4 个答案:

答案 0 :(得分:5)

我在一个小样本项目中检查了这个,这对我有用:

// Loop through all the rows of your grid
foreach (DataGridViewRow row in this.dgvMailPreferences.Rows)
{
    // Loop through all the cells of the row
    foreach (DataGridViewCell cell in row.Cells)
    {
        // Check if the cell type is CheckBoxCell
        // If not, check the next cell
        if (!(cell is DataGridViewCheckBoxCell)) continue;

        // Set the specific cell to read only, if the cell is not checked
        cell.ReadOnly = !Convert.ToBoolean(cell.Value);
    }
}

此外,您可以添加一个事件来跟踪单元格更改,以激活对单击的单元格的只读:

private void dgvMailPreferences_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    if (!(e.RowIndex >= 0 && e.ColumnIndex >= 0)) return;

    DataGridViewCell cell = ((DataGridView)sender).Rows[e.RowIndex].Cells[e.ColumnIndex];

    if (!(cell is DataGridViewCheckBoxCell)) return;

    cell.ReadOnly = !System.Convert.ToBoolean(cell.Value);
}

(完成更改后发生火灾并留下电池。)

您可以使用Ivan Stoev Dotnetfiddle

处的小提琴构建示例项目
using System;
using System.Collections.Generic;
using System.Data;
using System.Windows.Forms;

namespace Samples
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var form = new Form();
            var dgv = new DataGridView { Dock = DockStyle.Fill, Parent = form };
            form.Load += (sender, e) =>
            {
                var dt = GetData();
                dgv.DataSource = dt;
                dgv.Columns["Mail Preference Description"].Width = 250;
                dgv.Columns["Post"].Width = 50;
                dgv.Columns["SMS"].Width = 50;
                dgv.Columns["Email"].Width = 50;
                dgv.Columns["Telephone"].Width = 75;
                dgv.Columns["SEQ_ID"].Visible = false;
                dgv.Columns["MAIL_PREFERENCE_ID"].Visible = false;
                foreach (DataGridViewRow row in dgv.Rows)
                {
                    foreach (DataGridViewCell cell in row.Cells)
                    {
                        if (cell.Value is bool && (bool)cell.Value == false)
                            cell.ReadOnly = true;
                    }
                }
            };
            Application.Run(form);
        }

        static DataTable GetData()
        {
            var dt = new DataTable();
            dt.Columns.Add("SEQ_ID", typeof(int));                              // SEQ_ID
            dt.Columns.Add("MAIL_PREFERENCE_ID", typeof(string));               // MAIL_PREFERENCE_ID
            dt.Columns.Add("Mail Preference Description", typeof(string));      // MAIL_PREFERENCE_DESC
            dt.Columns.Add("Post", typeof(bool));                               // POST
            dt.Columns.Add("SMS", typeof(bool));                                // SMS
            dt.Columns.Add("Email", typeof(bool));                              // EMAIL
            dt.Columns.Add("Telephone", typeof(bool));                          // TELEPHONE

            dt.Rows.Add(1, "1", "Membership", true, true, true, true);
            dt.Rows.Add(2, "2", "Monthly Newsletter", false, false, true, false);
            dt.Rows.Add(3, "3", "Mothhly Technical Briefing", false, false, true, false);
            dt.Rows.Add(4, "4", "Magazine", false, false, true, false);
            dt.Rows.Add(5, "5", "Branch Mailings", false, true, true, false);
            dt.Rows.Add(6, "6", "Events", true, true, true, true);
            dt.Rows.Add(7, "7", "Qualifications", true, true, true, true);
            dt.Rows.Add(8, "8", "Training", true, true, true, true);
            dt.Rows.Add(9, "9", "Recruitment", true, true, true, true);
            dt.Rows.Add(10, "A", "General", true, true, true, true);

            return dt;
        }
    }
}

答案 1 :(得分:1)

试试这个

((DataGridViewCheckBoxCell)Rows[Index].Cells["colName"]).ReadOnly = true;

希望它适合你。

答案 2 :(得分:0)

根据我的理解,在填充时,如果复选框的初始值为false,那么它应该是只读的。

尝试使用以下

设置只读值
// not setting the datagridview cell to readonly
foreach (DataGridViewRow row in dgvMailPreferences.Rows) {
    foreach (DataGridViewCell cell in row.Cells) {
        if (cell is DataGridViewCheckBoxCell) {
            DataGridViewCheckBoxCell checkBoxCell = cell as DataGridViewCheckBoxCell;
            //What is the initial  value in the checkbox
            bool isChecked = checkBoxCell.Value as bool;
            //set to read only if not checked
            checkBoxCell.ReadOnly = !isChecked;                 
        }
    }
}

答案 3 :(得分:0)

修改

好的,我意识到小提琴代码不是你的(我应该仔细阅读)。我能够使用您问题中的代码重新创建它。我看到现在的问题,就是这一行:

if(((DataGridViewCheckBoxCell)row.Cells[cell.ColumnIndex]).Selected == false)
  

您正在测试“已选择”,这不是您想要的,您想要针对单元格的“值”进行测试。

如果你看看其他答案中的代码,这就是他们所展示的内容。

原始答案:留给其他人

运行你的代码(小提琴)复选框确实是只读的,虽然它们看起来没有显示为灰色,就像它们被禁用一样(这是我认为你正在寻找的)你能否确认你是否能够实际检查复选框或不?

很遗憾,您无法直接停用该复选框。

如果这是您想要的,那么您有几个选项,您可以更改单元格的BackColor,这可能就足够了,但这实际上不会改变复选框本身的颜色。

您也可以自己绘制控件,here是类似教程的微软指南。

或者你可以创建一个禁用的单元格,并用它替换你需要的单元格。这不是太多的工作,特别是当someone已经为你完成时!