简体   繁体   English

我无法在 datagridview 中编辑一行

[英]I can't edit a row in the datagridview

I am trying to edit a row from the datagridview.我正在尝试从 datagridview 编辑一行。 Every row has a button.每行都有一个按钮。 When I press one of the rows button, a second form opens and show me the information in textboxes about that row and I need to edit what I want.当我按下其中一个行按钮时,会打开第二个表单,并在文本框中显示有关该行的信息,我需要编辑我想要的内容。

The problem is that I already wrote the code for editing but I can't add the DataGridViewCellEventArgs in the button function, or I can't use RowIndex to edit a specific row.问题是我已经编写了编辑代码,但是我无法在按钮 function 中添加 DataGridViewCellEventArgs,或者我无法使用 RowIndex 编辑特定行。

Here is the code:这是代码:

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();
}

and here is the code from the main form with the dgv这是带有 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();

How I can use RowIndex in the button function.如何在按钮 function 中使用 RowIndex。 How I can add DataGridViewCellEventArgs.如何添加 DataGridViewCellEventArgs。

It is seldom a good idea to access the displayed data in the DataGridView directly.直接访问 DataGridView 中显示的数据很少是一个好主意。 You should separate the way that data is displayed from the actual values.您应该将数据的显示方式与实际值分开。 This way you can easily change the display, without having to change the code that uses the data.这样您就可以轻松更改显示,而无需更改使用数据的代码。

Apparently your DataGridView shows several properties of a sequence of Contacts.显然,您的 DataGridView 显示了一系列联系人的几个属性。 Every Row shows one Contact:每行显示一个联系人:

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

You have added DataGridViewColumns to your DataGridView.您已将DataGridViewColumns添加到 DataGridView。 Every DataGridViewColumn shows one property.每个 DataGridViewColumn 显示一个属性。 The name of the property that should be shown is in DataGridViewColumn.DataPropertyName应显示的属性名称位于DataGridViewColumn.DataPropertyName

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

Now all you have to do is, get your data and put them in the DataSource of the DataGridView:现在您所要做的就是,获取您的数据并将它们放入 DataGridView 的 DataSource 中:

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

Now every change that the operator edits, is automatically updated in the DataSource.现在,操作员编辑的每个更改都会在 DataSource 中自动更新。 Every change that your program makes to the data source is automatically displayed.您的程序对数据源所做的每一次更改都会自动显示出来。

Programmatically add a contact:以编程方式添加联系人:

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

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

Access edited contacts, for instance after pressing a button:访问已编辑的联系人,例如按下按钮后:

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

Every row in your DatagridView has a button. DatagridView 中的每一行都有一个按钮。 If the operator pressed the button you want to use the Contact that is displayed in that row to do something.如果操作员按下了您想使用该行中显示的联系人执行某项操作的按钮。

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);
}

You can do this in one big statement.你可以在一个大声明中做到这一点。 Not sure if this improves readability though.不确定这是否会提高可读性。

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
        }
    }
}

Be careful: you attach the original unedited contact to the dialog box.请注意:您将原始未编辑的联系人附加到对话框中。 If the operator changes values and presses Cancel, the original contact might still be changed.如果操作员更改值并按取消,则原始联系人可能仍会更改。 Better is to attach a Cloned contact to the dialog, and if needed use the properties of the edited cloned contact to update the original contact.最好将克隆联系人附加到对话框,如果需要,使用编辑的克隆联系人的属性来更新原始联系人。

Did you see, that because I didn't do everything in one big procedure, the procedures are much easier to understand.你有没有看到,因为我没有在一个大程序中做所有事情,所以这些程序更容易理解。 They are much easier to be changed slightly, and they can also be reused easily.它们更容易稍微改变,也可以很容易地重复使用。

For instance, if you decide not to add a column with buttons, because you don't want to display 50 buttons in your form, you decide to add one button to edit the "currently selected row", code changes will be minimal:例如,如果您决定不添加带有按钮的列,因为您不想在表单中显示 50 个按钮,您决定添加一个按钮来编辑“当前选定的行”,代码更改将是最小的:

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

This procedure can of course also be reused if you want to add a menu item to edit the current row.如果您想添加菜单项来编辑当前行,当然也可以重复使用此过程。

Because you separated the way that Contacts are displayed in the datagridview from the actual contacts, code changes will be small if you decide to display the Contact differently, for instance if you decide not to display the Id of the contact anymore, or if you plan to use a Japanese method of displaying the birthday.因为您将联系人在 datagridview 中的显示方式与实际联系人分开,所以如果您决定以不同方式显示联系人(例如,如果您决定不再显示联系人的 ID,或者如果您计划使用日本的方法来显示生日。 Or if you implement ordering of the data.或者,如果您实现数据排序。 The BindingList always contains the internal contact data. BindingList 始终包含内部联系人数据。

Similarly, if you want to change your contact.同样,如果您想更改联系人。 For example separate the firstname and the lastName, but still want to display them in one column, code changes will be very small.比如把firstname和lastName分开,但还是想在一列中显示,代码改动会很小。

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

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