web-dev-qa-db-ja.com

ボタンコントロール付きのDataGridView-行の削除

DataGridViewの各行の最後に[削除]ボタンが必要です。それをクリックして、グリッドのデータソースであるバインディングリストから目的の行を削除します。

しかし、私はそれを行うことができないようです。製品クラスでボタンオブジェクトを作成し、そのオブジェクトをリストから削除するために一意のIDでインスタンス化しました。しかし、ボタンは行に表示されていません。

Screen shot

フォームにはTextBoxがあり、ユーザーはテキストを入力できます。ユーザーが[追加]ボタンを押すと、提供されたフィールドで製品の新しいオブジェクトがインスタンス化され、BindingListに追加されます。

最後に、このリストはDataGridViewにバインドされ、詳細がグリッドに表示されます。 (私はこの部分を行いました)。

最後に保存ボタンをクリックすると、リストがDBに保存されます。

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;
    }
    .....
}
7
namsu

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

ボタンのテキストを設定

次のいずれかのオプションを使用できます。

TextDataGridViewButtonColumnプロパティを設定し、そのUseColumnTextForButtonValuetrueに設定すると、その列の各セルにテキストが表示されます。

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

ボタンのクリックイベントを処理する

ボタンのクリックを処理するには、グリッドの CellClick または CellContentClick イベントを処理できます。両方のイベントは、クリックして押すと発生します 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 で述べられているように、BindingListを使用する場合、変更のたびにグリッドのデータソースをnullに設定し、バインディングリストに戻す必要はありません。 BindingList自体は、DataGridViewへの変更を反映しています。
17
Reza Aghaei