简体   繁体   中英

Showing more than one row in DataGridView in C#

Why I can't show more than one row on DataGridView in C#?

Here is my code:

btnAdd_Click Event:

    QuestionGroup _question = new QuestionGroup(); 
    _question.QGID = QGID; // int
    _question.QGName = QGName; // string
    ToQuestionList(_question);
    MessageBox.Show("Item Added successfully.", Application.ProductName, MessageBoxButtons.OK, 
                     MessageBoxIcon.Information);

ToQuestionList function:

    void ToQuestionList(QuestionGroup q)
    {
        Questions.Add(q);
        dataGridView1.DataSource = Questions;
    }

Question class:

    public class QuestionGroup
        {
            public int QGID { get; set; }
            public string QGName { get; set; }
        }

Your problem is caused by the fact the DataGridView looks at the object that you want to set as its datasource. It discovers that is the same object binded at the first click and so it doesn't change its display. Setting the Datasource with the same object doesn't force the DataGridView to look if there are more elements in the object.

A first fix could be:

void ToQuestionList(QuestionGroup q)
{
    Questions.Add(q);
    dataGridView1.DataSource = null;
    dataGridView1.DataSource = Questions;
}

This will force the grid to rebind everything and the new elements will be displayed.
However there is a better approach using a BindingSource instance.

You need to declare, at the class level, an object of type BindingSource like this

public class Form1: Form
{
     BindingSource data = new BindingSource();
     List<QuestionGroup> Questions = new List<QuestionGroup>();
     ....

then in the Form Load event you should add these lines

public void Form_Load(object sender, EventArgs e)
{
     data.DataSource = Questions;
     dataGridView1.DataSource = data;
     ....

and finally you could change the ToQuestionList to (but at this point you can also remove it)

void ToQuestionList(QuestionGroup q)
{
    bs.Add(q);
}

You are correct, if you want to show data in a DataGridView it is wise not to edit the rows and the cells directly, but to use a DataSource.

What type of DataSource you use depends on what you want to do with your data.

  • If you only want to show the initial data, don't want to change it, then you can use any list / array for it, maybe even an IEnumerable or ICollection is enough.
  • If you want to change the data to be shown, you need to use an object that implements IBindingList. This ensures that changes that your software makes to the data are shown in the DataGridView, and changes made by the operator in the DataGridView are updated in the source data.

For the latter case, it is enough to show your data in a BindingList

// the DataGridView that shows Customers:
private DataGridView CustomerView => this.customerView;

// The data in the DataGridView:
private BindingList<Customer> DisplayedCustomers
{
    get => (BindingList<Customer>)this.CustomerView.DataSource;
    set => this.CustomerView.DataSource = value;
}

// constructor:
public MyForm()
{
    InitializeComponent();   // creates member this.customerView;

    // initally show an empty customers collection
    this.DisplayedCustomers = new BindingList<Customer>();
}

After a while (on form loading? after a button press? Fetch Customers, and show the data:

private void InitCustomerView()
{
    var customers = this.GetCustomers().ToList();
    this.DisplayedCustomers = new BindingList<Customer> customers;
}

If you've defined your columns correctly, this is enough to show your data, one row per customer:

dataGridViewColumnId.DataPropertyName = nameof(Customer.Id);
dataGridViewColumnName.DataPropertyName = nameof(Customer.Name);
...

To add / remove a displayed Customer:

private void AddCustomer(Customer customer)
{
    this.DisplayedCustomers.Add(customer);
}

private void RemoveCustomer(int customerId)
{
    int index = this.FindCustomerIndex(customerId);
    this.DisplayedCustomers.RemoveItem(index);
}

private int FindCustomerIndex(int customerId)
{
    // TODO: use (Collection<Customer>)this.DisplayedCustomers to find index
    // of customer with Id == customerId        
}

To fetch all Customers after the operator signaled he finished editing the Customers:

private void ButtonFinishedEditing_Clicked(object sender, ...)
{
    ICollection<T> customers = this.DisplayedCustomers();
    this.ProcessEditedCustomers(customers);
}

Conclusion:

Put your data in a BindingList<T> , and put this in the DataSource of the datagridview. After every accepted edited row, the data is updated in the BindingList.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM