【问题标题】:DataGridView with Button Control - Delete Row带有按钮控件的 DataGridView - 删除行
【发布时间】:2015-11-05 11:29:00
【问题描述】:

我想在DataGridView 的每一行末尾添加一个删除按钮,然后单击该按钮,我想从绑定列表中删除所需的行,该绑定列表是我的网格的数据源。

但我似乎做不到我已经在产品类中创建了一个按钮对象并使用唯一 id 实例化它以从列表中删除该对象。但按钮未显示在行中。

表单中有文本框,用户可以输入文本,当他们按下添加按钮时,将使用提供的字段实例化一个新的产品对象,然后将其添加到BindingList

最后,这个列表绑定到DataGridView,详细信息显示在网格中。 (我已经完成了这部分)。

最后通过点击保存按钮将列表保存在数据库中。

public class Product{
    public string Brand { get; set; }   
    public int ProductPrice { get; set; }
    public int Quantity { get; set; }

    public product(string brand,int productPrice, int quantity){   
        this.Brand = brand;
        this.ProductPrice = productPrice;
        this.Quantity = quantity;
    }   
}

public partial class MainForm: Form{
    .....
    BindingList<Product> lProd = new BindingList<Product>();
    private void btnAddProduct_Click(object sender, EventArgs e){
        string Brand = txtProBrand.Text;
        int Price = Convert.ToInt32(txtPrice.Text);
        int Quantity = Convert.ToInt32(txtQuantity.Text);

        Product pro = new Product(Brand, Price, Quantity);
        lProd.Add(pro);
        dataGridView1.DataSource = null;
        dataGridView1.DataSource = lProd;
    }
    .....
}

【问题讨论】:

  • 我想这个问题之前已经回答过了。 stackoverflow.com/questions/21191950/how-to-add-a-button-to-a-column-in-the-datagridview
  • 我似乎无法在列表中执行此操作。我可以在数据表中添加一个按钮。如何在列表中做到这一点??
  • 如果列表中您的意思是您的绑定列表,那么答案是您不想这样做:) 您的网格绑定到您的 T 绑定列表,并且列反映了您的对象中的属性键入 T,并且您不希望对象中有“删除”属性 - 这没有多大意义。将 datagridviwe 绑定到您的列表(像以前一样),然后手动添加一个带有删除按钮的列,就像这个答案所暗示的那样。

标签: c# .net winforms datagridview bindinglist


【解决方案1】:

要在DataGridView 行上显示按钮,您应该在网格的列中添加DataGridViewButtonColumn。以下是使用按钮栏时应了解的一些常见任务:

  • 将按钮列添加到 DataGridView
  • 在按钮上显示图像
  • 设置按钮文本
  • 处理按钮的点击事件

向 DataGridView 添加按钮列

要在网格的每一行上显示一个按钮,您可以通过编程方式或使用设计器将DataGridViewButtonColumn 添加到网格的列中:

var deleteButton=new DataGridViewButtonColumn();
deleteButton.Name="dataGridViewDeleteButton";
deleteButton.HeaderText="Delete";
deleteButton.Text="Delete";
deleteButton.UseColumnTextForButtonValue=true;
this.dataGridView1.Columns.Add(deleteButton);

在按钮上显示图像

如果您更喜欢在按钮上绘制图像,您应该在资源中有一个图像,然后处理您的网格的CellPainting 事件:

void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (e.RowIndex == dataGridView1.NewRowIndex || e.RowIndex < 0)
        return;

    if (e.ColumnIndex == dataGridView1.Columns["dataGridViewDeleteButton"].Index)
    {
        var image = Properties.Resources.DeleteImage; //An image
        e.Paint(e.CellBounds, DataGridViewPaintParts.All);
        var x = e.CellBounds.Left + (e.CellBounds.Width - image.Width) / 2;
        var y = e.CellBounds.Top + (e.CellBounds.Height - image.Height) / 2;
        e.Graphics.DrawImage(image, new Point(x, y));

        e.Handled = true;
    }
}

设置按钮文字

您可以使用以下任一选项:

您可以设置DataGridViewButtonColumnText 属性并将其UseColumnTextForButtonValue 设置为true,这样文本将显示在该列的每个单元格上。

deleteButton.Text="Delete";
deleteButton.UseColumnTextForButtonValue=true;

您也可以使用单元格的Value 属性:

this.dataGridView1.Rows[1].Cells[0].Value = "Some Text";

作为另一种选择,您可以处理网格的CellFormatting 事件。当您想为按钮设置不同的文本时,这种方式可能很有用。

void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    //If this is header row or new row, do nothing
    if (e.RowIndex < 0 || e.RowIndex == this.dataGridView1.NewRowIndex)
        return;

    //If formatting your desired column, set the value
    if (e.ColumnIndex=this.dataGridView1.Columns["dataGridViewDeleteButton"].Index)
    {
        e.Value = "Delete";
    }
}

处理按钮的点击事件

要处理点击按钮,您可以处理网格的CellClickCellContentClick 事件。这两个事件都通过单击和按 Space 键触发。

void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
    //if click is on new row or header row
    if( e.RowIndex == dataGridView1.NewRowIndex || e.RowIndex < 0)
        return;

    //Check if click is on specific column 
    if( e.ColumnIndex  == dataGridView1.Columns["dataGridViewDeleteButton"].Index)
    {
        //Put some logic here, for example to remove row from your binding list.
        //yourBindingList.RemoveAt(e.RowIndex);

        // Or
        // var data = (Product)dataGridView1.Rows[e.RowIndex].DataBoundItem;
        // do something 
    }
}

获取点击事件记录的数据

你有e.RowIndex,那么就可以拿到行后面的数据了:

 var data = (Product)dataGridView1.Rows[e.RowIndex].DataBoundItem;
// then you can get data.Id, data.Name, data.Price, ...

您需要将其转换为重新计算的数据类型,例如Product

如果数据绑定已设置为使用 DataTable,则要转换的类型为 DataRowView

您也可以使用dataGridView1.Rows[e.RowIndex].Cells[some cell index].Value 来获取特定单元格的值,但是DataBoundItem 更有意义。

注意

  • 正如Ivan 在 cmets 中提到的,当您使用BindingList 时,您不需要将网格的数据源设置为空并在每次更改时返回绑定列表。 BindingList 本身反映了对您的 DataGridView 的更改。

【讨论】:

  • 嗨,雷扎。我正要回答这个问题,但注意到你已经回答了。您能否在回答建议中包含删除将 DataSource 设置为 null 的行,然后在每次添加到绑定列表时添加到绑定列表。干杯。
  • 您好,感谢您对 Ivan 的评论,请随时编辑我的答案并使其更有用:)
  • 谢谢,但我不太擅长像你这样的解释 :-) 我提到的代码除了冗余和低效之外,还需要 OP 重新创建有问题的列,以防 AutoGenerateColumns是真的,我敢打赌。
猜你喜欢
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 2018-12-13
  • 2020-06-22
  • 2021-12-16
  • 1970-01-01
相关资源
最近更新 更多