简体   繁体   English

如何在C#Winforms中不使用数据库的情况下在列表上使用DatagridView

[英]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. 在我的项目中,我想从文件中读取数据并将DataGridView更新为一个简单的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. 在google搜索中看到的大多数解决方案中,我都提供了有关如何使用DatagridView和数据库连接来更新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. 我的答案有很多建议,包括添加基于INotifyProperty和IBindingList的实现,这可能是一个过大的杀伤力。

I only aim to post my solution which involves using Datagridview to update a list. 我只打算发布涉及使用Datagridview更新列表的解决方案。 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. 此处使用的代码段是一个大型项目的一部分,该项目将数据从Datagridview更新到列表,然后再返回,这是一个很大的挑战,因为最初需要使用数据库来实现,而依赖关系则需要删除。

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. 因此,阅读后,您将获得一系列MyData对象。 You want to display all MyData objects (or a subsection) in a DataGridView. 您要在DataGridView中显示所有MyData对象(或子部分)。

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. 按下确定按钮后,您想要从DataGridView读取所有MyData对象并将它们保存在文件中。

Most of your work can be done using the forms designer. 您的大部分工作都可以使用表单设计器来完成。

  • Open your form class in the designer 在设计器中打开表单类
  • Drag a DataGridView on this form 在此表单上拖动一个DataGridView
  • Drag a BindingSource on this form 在此表单上拖动BindingSource
  • Right click BindingSource and select properties 右键单击BindingSource并选择属性
  • Click in the properties window in DataSource on the arrow on the right 在右侧的箭头中,单击“数据源”中的属性窗口。
  • If MyData is not visible there, select Add Project Data Source 如果MyData在此处不可见,请选择“添加项目数据源”。
  • In the new window select object 在新窗口中选择对象
  • Select the added data source as DataSource of your BindingSource 选择添加的数据源作为BindingSource的DataSource
  • In the properties of DataGridView, assign your bindingSource to the DataSource 在DataGridView的属性中,将您的bindingSource分配给DataSource

And suddenly: your DataGridView has the columns of the public properties of MyData. 突然之间:您的DataGridView具有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) 如果您不希望操作员执行此操作,请调整DataGridView属性。如果列的显示值不符合您的喜好,请编辑列属性(不同的标题文本,不同的显示格式,不同的背景颜色等)

Here is an example where I have used the DatagridView to perform Insert Update and Delete on a List (List of Class objects PersonState ). 这是一个示例,其中我使用DatagridView在列表(类对象PersonState列表)上执行插入更新和删除。

The DatagridView's Datasource needs to contain a DataTable, to bridge this gap, I have used a function named ConvertToDatatable() . DatagridView的数据源需要包含一个DataTable,为了弥合这一差距,我使用了一个名为ConvertToDatatable()的函数。

As my starting point I began with a project suggested on another link by Anup Kumar Sharma. 首先,我从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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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