首页 > 解决方案 > 我无法在 datagridview 中编辑一行

问题描述

我正在尝试从 datagridview 编辑一行。每行都有一个按钮。当我按下其中一个行按钮时,会打开第二个表单,并在文本框中显示有关该行的信息,我需要编辑我想要的内容。

问题是我已经编写了编辑代码,但无法在按钮功能中添加 DataGridViewCellEventArgs,或者无法使用 RowIndex 编辑特定行。

这是代码:

public void btnUpdate_Click(object sender, EventArgs e)
{
    SqlConnection conn = new SqlConnection(@"Data Source=DESKTOP-VUPD668;Initial Catalog=dbApp;Integrated Security=True");
    SqlCommand cmd;
    cmd = new SqlCommand("UPDATE tableApplication SET Name='" + txtName.Text + "',Package='" + txtPackage.Text + "',Hour='" + txtHour.Text + "',Date='" + txtDate.Text + "',Phone='" + txtPhone.Text + "',Observations='" + txtObservations.Text + "' WHERE ID=" + f1.dgvContactList.Rows[rowIndex].Cells[0].Value.ToString(), conn);
    conn.Open();

    cmd.ExecuteNonQuery();

    conn.Close();
    MessageBox.Show("Edit was saved");
    this.Close();
}

这是带有 dgv 的主表单中的代码

public void dgvContactList_CellContentClick(object sender, DataGridViewCellEventArgs e)
{       
    if (e.ColumnIndex == 7)
    {            
        formAddEditContact f2 = new formAddEditContact();
        int rowIndex = e.RowIndex;
        formContact f1 = new formContact();
        f2.lblTitle.Text = "Edit";
        f2.btnSave.Visible = false;
        f2.btnUpdate.Visible = true;
        
        f2.btnDelete.Visible = true;
        f2.txtName.Text = f1.dgvContactList.Rows[rowIndex].Cells[1].Value.ToString();
        f2.txtPackage.Text = f1.dgvContactList.Rows[rowIndex].Cells[2].Value.ToString();
        f2.txtHour.Text = f1.dgvContactList.Rows[rowIndex].Cells[3].Value.ToString();
        f2.txtDate.Text = f1.dgvContactList.Rows[rowIndex].Cells[4].Value.ToString();
        f2.txtPhone.Text = f1.dgvContactList.Rows[rowIndex].Cells[5].Value.ToString();
        f2.txtObservations.Text = f1.dgvContactList.Rows[rowIndex].Cells[6].Value.ToString();
        f2.ShowDialog();

如何在按钮功能中使用 RowIndex。如何添加 DataGridViewCellEventArgs。

标签: c#winforms

解决方案


直接访问 DataGridView 中显示的数据很少是一个好主意。您应该将数据的显示方式与实际值分开。这样您就可以轻松更改显示,而无需更改使用数据的代码。

显然,您的 DataGridView 显示了一系列联系人的几个属性。每行显示一个联系人:

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

您已添加DataGridViewColumns到 DataGridView。每个 DataGridViewColumn 显示一个属性。应显示的属性名称位于DataGridViewColumn.DataPropertyName

DataGridViewColumn columnBirthDay = new DataGridViewColumn();
columnBirthDay.DataPropertyName = nameof(Contact.BirthDay);
... // set other properties.

现在您所要做的就是,获取您的数据并将它们放入 DataGridView 的 DataSource 中:

IEnumerable<Contact> contactsToDisplay = ...
this.DataGridViewContacts.DataSource = new BindingList<Contact>(contactsToDisplay);

现在,操作员编辑的每个更改都会在 DataSource 中自动更新。您的程序对数据源所做的每一次更改都会自动显示出来。

以编程方式添加联系人:

BindingList<Contact> DisplayedContacts => (BindingList<Contact>)this.DataGridViewContacts.DataSource;

private void DisplayContact(Contact contact)
{
    this.DisplayedContacts.Add(contact);
}

访问已编辑的联系人,例如按下按钮后:

private void OnButtonOkClicked(object sender, ...)
{
     Collection<Contact> editedContacts = this.DisplayedContacts;
     this.ProcessEditedContacts(editedContacts);   
}

DatagridView 中的每一行都有一个按钮。如果操作员按下了您想使用该行中显示的联系人执行某项操作的按钮。

private Contact GetContact(DataGridViewRow row)
{
    return (Contact)row.DataBoundItem;
}

private void dgvContactList_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    // in baby steps:
    DataGridView dataGridView = (DataGridView)sender;
    DataGridViewRow row = dataGridView.Rows[e.RowIndex];
    Contact contact = GetContact(row);
    EditContact(contact);
}

你可以在一个大声明中做到这一点。不确定这是否会提高可读性。

private void EditContact(Contact contact)
{
    using (var dlg = new EditContactDlg())
    {
        dlg.Contact = contact;
        ... // other dialog properties

        var dialogResult = dlg.Show(this);
        if (dlgResult == DialogResult.OK)
        {
            ... // process edited contact
        }
    }
}

请注意:您将原始未编辑的联系人附加到对话框中。如果操作员更改值并按取消,则原始联系人可能仍会更改。最好将克隆联系人附加到对话框,如果需要,使用编辑的克隆联系人的属性来更新原始联系人。

你有没有看到,因为我没有在一个大程序中做所有事情,所以这些程序更容易理解。它们更容易稍微改变,也可以很容易地重复使用。

例如,如果您决定不添加带有按钮的列,因为您不想在表单中显示 50 个按钮,您决定添加一个按钮来编辑“当前选定的行”,代码更改将是最小的:

private void OnButtonEditCurrentRow_Clicked(object sender, ...)
{
    DataGridViewRow row = this.DataGridViewContacts.CurrentRow;
    Contact contact = GetContact(row);
    EditContact(contact);
}

如果您想添加菜单项来编辑当前行,当然也可以重复使用此过程。

因为您将联系人在 datagridview 中的显示方式与实际联系人分开,所以如果您决定以不同方式显示联系人,代码更改将很小,例如,如果您决定不再显示联系人的 ID,或者如果您计划使用日本的方法来显示生日。或者,如果您实现数据排序。BindingList 始终包含内部联系人数据。

同样,如果您想更改联系人。比如把firstname和lastName分开,但还是想在一列中显示,代码改动会很小。


推荐阅读