简体   繁体   中英

How to use DatagridView on a List without using Database in C# Winforms

In my project I wanted to read data from a file and update the DataGridView to a simple List. I wanted this so that the list can be updated at run time and then upon save wanted the final content of the list to be updated to a file.

In most of the solutions seen on google search I came up with examples of how to use a DatagridView with Database connection used to update the DatagridView. for Insert, Update and Delete operations. Lot of suggestions for my answer included adding INotifyProperty and IBindingList based impelementations which are probably an overkill.

I only aim to post my solution which involves using Datagridview to update a list. The code snippet used here is part of a huge project where updating the data from Datagridview to the List and back was a very big challenge due to initial impelementation with Database, whose dependency needed to be removed.

At the point of posting this question, I have a solution to my problem. To arrive at this problem I have taken bits and pieces of suggestions from various previous questions. I am not looking for suggestions in comments. If anyone wants to show me better way to solve this problem, please post an answer with working code.

So after reading, you have a sequence of MyData objects. You want to display all MyData objects (or a subsection) in a DataGridView.

Operators may change the displayed values, add some new rows, or delete rows. Some columns may be readonly and can't be changed

After pressing the OK-button, you want to read all MyData objects from the DataGridView and Save them in a file.

Most of your work can be done using the forms designer.

  • Open your form class in the designer
  • Drag a DataGridView on this form
  • Drag a BindingSource on this form
  • Right click BindingSource and select properties
  • Click in the properties window in DataSource on the arrow on the right
  • If MyData is not visible there, select Add Project Data Source
  • In the new window select object
  • Select the added data source as DataSource of your BindingSource
  • In the properties of DataGridView, assign your bindingSource to the DataSource

And suddenly: your DataGridView has the columns of the public properties of MyData. And magically, the columns have the correct type. They are able to display the values. Readonly properties have readonly Columns, read-write properties are editable.

To display your data:

void FillDataGridView(IEnumerable<MyData> dataToDisplay)
{
    this.bindingSource1.DataSource = new BindingList<MyData>(dataToDisplay.ToList();
}

To read all data after editing

IEnumerable<MyData> ReadDataGridView()
{
    return this.bindingSource1.List.Cast<MyData>();
}

This enables the operator to add and delete rows and to edit the values. If you don't want the operator to do this, adjust the DataGridView properties If the displayed values of the columns are not to your liking, edit the column properties (different header text, different display format, different backgroundcolor etc)

Here is an example where I have used the DatagridView to perform Insert Update and Delete on a List (List of Class objects PersonState ).

The DatagridView's Datasource needs to contain a DataTable, to bridge this gap, I have used a function named ConvertToDatatable() .

As my starting point I began with a project suggested on another link by Anup Kumar Sharma.

在此处输入图片说明

Using the following code:

using System;
using System.Collections.Generic;
using System.Data;
using System.Windows.Forms;

namespace InsertUpdateDelete {
    public partial class Form1 : Form {
        public class PersonState {
            public string Name { get; set; }
            public string State { get; set; }
        }
        public List<PersonState> listOfPersonState;
        public Form1() {
            InitializeComponent();
            listOfPersonState = new List<PersonState>();
        }
        //Display Data in DataGridView  
        private void DisplayData() {
            DataTable dt = new DataTable();
            dt = ConvertToDatatable();
            dataGridView1.DataSource = dt;
        }
        //Clear Data  
        private void ClearData() {
            txt_Name.Text = "";
            txt_State.Text = "";
        }
        public DataTable ConvertToDatatable() {
            DataTable dt = new DataTable();
            dt.Columns.Add("Name");
            dt.Columns.Add("State");
            foreach (var item in listOfPersonState) {
                var row = dt.NewRow();
                row["Name"] = item.Name;
                row["State"] = item.State;
                dt.Rows.Add(row);
            }
            return dt;
        }
        private void AddToList(string text1, string text2) {
            listOfPersonState.Add(new PersonState { Name = text1, State = text2 });
        }
        private void UpdateToList(string text1, string text2) {
            int index = dataGridView1.SelectedRows[0].Index;
            listOfPersonState[index] = new PersonState { Name = text1, State = text2 };
        }
        private void DeleteToList() {
            int index = dataGridView1.SelectedRows[0].Index;
            listOfPersonState.RemoveAt(index);
        }
        private void btn_Insert_Click(object sender, EventArgs e) {
            if (txt_Name.Text != "" && txt_State.Text != "") {
                AddToList(txt_Name.Text, txt_State.Text);
                //MessageBox.Show("Record Inserted Successfully");
                DisplayData();
                ClearData();
            } else {
                MessageBox.Show("Please Provide Details!");
            }
        }
        private void btn_Update_Click(object sender, EventArgs e) {
            if (txt_Name.Text != "" && txt_State.Text != "") {
                if (dataGridView1.SelectedRows != null && dataGridView1.SelectedRows.Count > 0) {
                    UpdateToList(txt_Name.Text, txt_State.Text);
                    //MessageBox.Show("Record Updated Successfully");
                    DisplayData();
                    ClearData();
                }    
            } else {
                MessageBox.Show("Please Select Record to Update");
            }
        }
        private void btn_Delete_Click(object sender, EventArgs e) {
            if (dataGridView1.SelectedRows != null && dataGridView1.SelectedRows.Count > 0) {
                DeleteToList();
                //MessageBox.Show("Record Deleted Successfully!");
                DisplayData();
                ClearData();
            } else {
                MessageBox.Show("Please Select Record to Delete");
            }
        }

        private void dataGridView1_RowHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
            FillInputControls(e.RowIndex);
        }
        private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) {
            FillInputControls(e.RowIndex);
        }
        private void FillInputControls(int Index) {
            if (Index > -1) {
                txt_Name.Text = dataGridView1.Rows[Index].Cells[0].Value.ToString();
                txt_State.Text = dataGridView1.Rows[Index].Cells[1].Value.ToString();
            }
        }
    }
}

Learnings:

  1. Observe that I have used propertis in the class.

Instead of using:

public class PersonState {
    public string Name;
    public string State;
}

I have used:

public class PersonState {
    public string Name { get; set; }
    public string State { get; set; }
}

For some reason, the former does not work when trying to assing values.

  1. I have made the list of objects a class variable so that all functions can access that list directly instead of it being passed around as a parameter.

    public List<PersonState> listOfPersonState;

  2. I replaced the logic to Insert, Update and Delete to a DB, to Insert Update and Delete to a List.

     private void AddToList(string text1, string text2) { listOfPersonState.Add(new PersonState { Name = text1, State = text2 }); } private void UpdateToList(string text1, string text2) { int index = dataGridView1.SelectedRows[0].Index; listOfPersonState[index] = new PersonState { Name = text1, State = text2 }; } private void DeleteToList() { int index = dataGridView1.SelectedRows[0].Index; listOfPersonState.RemoveAt(index); } 

Note: I am assigning the Grid directly from the List, so my Grid and my List always have the same index because I am using the Display function to ensure this on Insert, update and delete Button operations.

private void DisplayData() {
    DataTable dt = new DataTable();
    dt = ConvertToDatatable();
    dataGridView1.DataSource = dt;
}
public DataTable ConvertToDatatable() {
    DataTable dt = new DataTable();
    dt.Columns.Add("Name");
    dt.Columns.Add("State");
    foreach (var item in listOfPersonState) {
        var row = dt.NewRow();
        row["Name"] = item.Name;
        row["State"] = item.State;
        dt.Rows.Add(row);
    }
    return dt;
}

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