在 DataGridView 中将自动生成的列设置为只读

Make auto generated column readonly in DataGridView

我有一个 DataGridView,它的 DataSource 是一个有五列的 DataTable。如果我尝试访问列的 ReadOnly 属性,像这样:

datagridview.Columns[1].ReadOnly = true; 

它抛出 NullReferenceExcpetion.

我知道这是由于框架如何管理其自动生成的列,如对 this question 的回答所述。

我的问题是:如何在自动生成数据源时将列设置为只读?

生成列后将列设置为只读

    private void Form1_Load(object sender, EventArgs e)
    {

        List<Student> allStudent = new List<Student>();

        for (int i = 0; i < 10; i++)
        {
            allStudent.Add(new Student { Name = "Student" + i, Roll = i + 1 });
        }

        dataGridView1.AutoGenerateColumns = true;
        dataGridView1.DataSource = allStudent;

        //Edited to show column count
        MessageBox.Show("Column count is " + dataGridView1.Columns.Count);

        foreach (DataGridViewColumn column in dataGridView1.Columns)
        {
            column.ReadOnly = true;
        }

    }

    public partial class Student
    {
        public string Name { get; set; }
        public int Roll { get; set; }
    }

以真正的 TEK 方式,我找到了解决我自己问题的方法:

为此,您需要使用 ColumnAdded 事件

datagridview.ColumnAdded += dataGridView_ColumnAdded;

然后在活动中,您可以按名称查看列:

  private void dataGridView_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
  {
        if (e.Column is DataGridViewColumn)
        {
            DataGridViewColumn column = e.Column as DataGridViewColumn;
            column.ReadOnly = true;
            if (column.Name == "first_name")
            {
                column.ReadOnly = false;
            }
        }
  }

无法真正说明为什么它不起作用,但使用以下代码进行简单测试:

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

    private void Form1_Load(object sender, EventArgs e)
    {
        dataGridView1.AutoGenerateColumns = true;
        dataGridView1.DataSource = GenerateData();

        dataGridView1.Columns[0].ReadOnly = true;
    }

    private List<DataSourceTest> GenerateData()
    {
        return new List<DataSourceTest>()
        {
            new DataSourceTest(1, "A"),
            new DataSourceTest(2, "B"),
            new DataSourceTest(3, "C"),
            new DataSourceTest(4, "D"),
            new DataSourceTest(5, "E"),
            new DataSourceTest(6, "F"),
        };
    }
}

public class DataSourceTest
{
    public DataSourceTest(int id, string name) { ID = id; Name = name; }
    public int ID { get; set; }
    public string Name { get; set; }
}

并将 gridview EditMode 设置为 EditOnEnter 这样我们就可以轻松地检查它是否是只读的,这表明它做得很好。

但是如果你仍然有问题,最好的办法是使用一个事件,最接近你问题的事件是 DataBindingComplete,它将在绑定已完成,因此到那时,您将拥有对所有列的完全访问权限,因为它们已经绑定到 gridview 对象。

双击 GridView 控件中的事件并添加你的只读 setter:

private void dataGridView1_DataBindingComplete(
    object sender, DataGridViewBindingCompleteEventArgs e)
{
    dataGridView1.Columns[0].ReadOnly = true;
}