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

C# 在DataGridView中将自动生成的列设为只读,c#,winforms,datagridview,.net-4.6,C#,Winforms,Datagridview,.net 4.6,我有一个DataGridView,它的DataSource是一个有五列的DataTable。如果我尝试访问列的只读属性,如下所示: datagridview.Columns[1].ReadOnly = true; 它抛出一个空引用expetion 我理解这是由于框架如何管理其自动生成的列,正如对的回答所指出的 我的问题是:当数据源自动生成时,如何使列只读?当列已生成时,如何使列只读 private void Form1_Load(object sender, EventArgs e)

我有一个
DataGridView
,它的
DataSource
是一个有五列的
DataTable
。如果我尝试访问列的
只读
属性,如下所示:

datagridview.Columns[1].ReadOnly = true; 
它抛出一个
空引用expetion

我理解这是由于框架如何管理其自动生成的列,正如对的回答所指出的


我的问题是:当数据源自动生成时,如何使列只读?

当列已生成时,如何使列只读

    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; }
    }
private void Form1\u加载(对象发送方,事件参数e)
{
List allStudent=新列表();
对于(int i=0;i<10;i++)
{
添加(新学生{Name=“Student”+i,Roll=i+1});
}
dataGridView1.AutoGenerateColumns=true;
dataGridView1.DataSource=allStudent;
//编辑以显示列计数
Show(“列计数为”+dataGridView1.Columns.count);
foreach(dataGridView1.Columns中的DataGridViewColumn列)
{
column.ReadOnly=true;
}
}
公立部分班学生
{
公共字符串名称{get;set;}
公共int Roll{get;set;}
}

以真正的TEK方式,我想出了一个解决我自己问题的办法:

为此,您需要使用添加的
事件

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

当它使用自动生成的列时,列计数将始终返回0,这意味着循环的内容将永远不会执行。检查
datagridview.Columns.Count
。谢谢您的回答。@Momit Column count返回0。对不起,我不知道该说什么。@TEK。。它是否仍然显示0(我将messagebox放在那里)。。但这是不可能的..直到
allStudent
变量为
null
。。我的示例显示了它
2
我认为这是DataGridView的一个问题,我可能无意中切换了一个属性。:)您是否尝试过使用
DataBindingComplete
事件?我几乎可以肯定,当该事件被触发时,您已经可以访问所有自动生成的列。。。试试看。只需打开“事件”面板,双击事件,然后调试并检查列。@balexandre是的,也可以!回答这个问题,我会接受的。这是一个让人头疼的问题,但是使用
databindingplete
事件对我来说很有效。显然,我在某个地方启用了一些属性标志,这导致了我的问题。然而,在这和我的答案之间,我的问题解决了。非常感谢。
private void dataGridView1_DataBindingComplete(
    object sender, DataGridViewBindingCompleteEventArgs e)
{
    dataGridView1.Columns[0].ReadOnly = true;
}