簡體   English   中英

如何從 DataGridView 讀取 C# 中的單元格值

[英]How can i read cell value in C# from DataGridView

我試圖為學校分配做一個 StackAutomata,我嘗試通過 for 找到單元格,但他們無法讀取它 int i、K 和 J 是在 do {} 之外創建的,而 cicle

for (int j = 0; j < gv1.Columns.Count; j++)
                {
                    if (input[i].ToString() == gv1.Rows[0].Cells[j].Value)
                    {
                        K = j;
                    }
                }

                J = K;
                


string a = verem.Pop();
for (int j = 0; j < gv1.Rows.Count; j++)
                    {
                        if (a == gv1.Rows[j].Cells[0].Value)
                        {
                            K = j;
                        }
                    }

我錯過了什么?

自己直接讀寫 DataGridView 很少是個好主意。 最好將 model 與 model 的顯示方式分開。

如果您的數據可以在沒有顯示的情況下存在,那么更改顯示方式會更容易,在另一個控件或不同格式中重用數據會更容易。 更容易對數據處理進行單元測試(無需表格)。 改變數據的內部布局,而不必改變那些顯示這些數據的人。

This separation between View and Model is implemented in extrema in the MVVM model, but windows Forms also supports this via Data Binding.

每當您擁有一個顯示有關一系列相似項的信息的控件時,無論是 ListBox、DataGridView 還是 GraphView,您都會發現它具有屬性DataSource

您所要做的就是將要顯示的數據放入 DataSource 中。 其他屬性定義必須如何顯示 DataSource 中的數據。 如果操作員改變了顯示的數據,那么原始數據會自動更新。

假設您的 DataGridView 必須顯示一組客戶:每行一個客戶。

您的 DataGridView 有幾個DataGridViewColumns 每列將顯示其中一個屬性的值。 要顯示的屬性名稱在屬性DataGridViewColumn.DataPropertyName中。

您所要做的就是制作一系列相似的項目,並將其分配給 DataGridView.DataSource。

一個例子會有所幫助。

假設您需要顯示一系列學生:

class Customer
{
    public int Id {get; set;}
    public string Name {get; set;}
    public DateTime BirthDay {get; set;}
    ...
}

您想在列中顯示這三個學生屬性。 使用 Visual Studio 設計器添加列並分配 DataPropertyName。 結果可以在InitializeComponents中找到,也可以自己做:

private readonly DataGridViewColumn columnId = new DataGridViewColumn();
private readonly DataGridViewColumn columnName = new DataGridViewColumn();
private readonly DataGridViewColumn columnBirthDay = new DataGridViewColumn();

// constructor
public MyForm()
{
    InitializeComponents();

    // define which column should display which Student property
    this.columnId.DataPropertyName = nameof(Student.Id);
    this.columnName.DataPropertyName = nameof(Student.Name);
    this.columnBirthDay.DataPropertyName = nameof(Student.BirthDay);

    // the the DataGridView to use these columns:
    this.dataGridView1.Columns.Add(this.columnId);
    this.dataGridView1.Columns.Add(this.columnName);
    this.dataGridView1.Columns.Add(this.columnBirthday);
}

通常您設置其他列屬性:您設置 Header 的文本,列順序,有時您定義顯示格式,例如:對於生日,您不想顯示一天中的時間。 但如果你願意,你可以將列 ID 設為只讀,使用粗體等。

請注意,到目前為止,我們在沒有一個實際學生的情況下完成了所有工作。

如果您想顯示學生但不想編輯它們,將它們放在一個集合中並將這個集合分配給 DataGridView 的數據源就足夠了

List<Student> students = ...
this.DataGridView1.DataSource = students;

但是,如果您希望操作員可以添加/刪除/更改/重新排序學生,您需要一種機制來更新學生集合中的更改。 如果您將數據放在BindingList中,這會自動完成

IList<Student> students = ...
BindingList<Student> displayedStudents = new BindingList<Student>(students);
this.DataGridView1.DataSource = displayedStudents;

顯示所有學生。 操作員可以根據需要添加/刪除/更改學生(除了您只讀的列)。 所有更改都會在 BindingList 中自動更新。

您可以從 BndingList 訂閱事件以對這些更改做出反應,但更常見的情況是您什么都不做,直到操作員告訴您他完成了更改,例如按下按鈕:

private void ButtonOk_Clicked(object sender, ...)
{
    DataGridView dataGridView = (DataGridView)sender;
    BindingList<Student> students = (BindingList<Student>)dataGridView.DataSource;

    foreach (Student student in students)
    {
         this.ProcessStudent(student);
    }

如果您保存了原始學生的副本,您可以檢測哪些學生被更改、添加、刪除並決定如何處理它們。 如果您需要對選定的行執行某些操作:

IEnumerable<Student> selectedStudents = this.dataGridView1.SelectedRows
    .Cast<DataGridViewRow>()
    .Select(row => row.DataBoundItem)
    .Cast<Student>();

一個不錯的功能:假設您希望您的軟件分配學生的 ID,而不是操作員。 然后,每當操作員想要添加新行時,您都必須使用唯一的 Id 創建學生。 這是通過處理事件BindingList.AddingNew來完成的

private void StudentCollection_AddingNew(object sender, AddingNewEventArgs e)
{
    // You need to make a Student with a unique Id:
    int newStudentId = this.CreateUniqueStudentId();
    e.NewObject = new Student
    {
        Id = newStudentId,
        // the operator has to fill in the rest of the properties
    }
}

您是否注意到您不必關心學生的顯示方式:您不必關心哪些屬性、什么顯示格式或列順序。 如果將來有人決定不再顯示學生的生日,或者重新排列列,可能會更改以大寫字母顯示學生的姓名:所有這些方法仍然有效。

for (int j = 0; j < gv1.Columns.Count; j++) {
  if (input[i].ToString() == gv1.Rows[0].Cells[j].Value.ToString()) {
    K = j;
  }
}

J = K;

string a = verem.Pop();
for (int j = 0; j < gv1.Rows.Count; j++) {
  if (a == gv1.Rows[j].Cells[0].Value.ToString()) {
    K = j;
  }
}

您無法將gridview.Rows.Cells.Value與字符串進行比較,因為它是Object ,只需添加.ToString()方法,它應該可以工作。

另外,請為您的變量找到一個更好的名稱,它會使您的代碼更具可讀性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM