C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

DataGridView 最終行だけ処理回避したい

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■90659 / inTopicNo.1)  DataGridView 最終行だけ処理回避したい
  
□投稿者/ ゆ牛 (4回)-(2019/04/02(Tue) 16:41:46)

分類:[.NET 全般] 

行追加オプション(ArrowUserToAddRows=true)のある
DataGridViewにおいて

「削除」ボタンが押されたらカーソル行を消す
という処理を作成中ですがうまくいきません。

// 「削除」ボタンが押されたときの処理
if (dGView1.CurrentCellAddress.Y >= 0 && dGView1.CurrentCellAddress.Y < dGView1.Rows.Count - 1)  // 最終行以外なら
{
  dGView1.Rows.RemoveAt(dGView1.CurrentCellAddress.Y);    // 削除
}

データがある行での「削除」は期待どおり動作しますが
最終行(空行)にカーソルがあるときに「削除」ボタンを押すと
最終よりひとつ上の行が消えてしまうようです。
原因は、dGView1.CurrentCellAddress.Y が一つ上の行番号を
示しているためです。
最終行での「削除」ボタンは無視したいのですが
何か方法はありますか?

環境 .NET 4

よろしくお願いします。

引用返信 編集キー/
■90660 / inTopicNo.2)  Re[1]: DataGridView 最終行だけ処理回避したい
□投稿者/ shu (1172回)-(2019/04/02(Tue) 17:06:20)
No90659 (ゆ牛 さん) に返信

        Dim row = DataGridView1.CurrentRow

        If Not row.IsNewRow Then
            DataGridView1.Rows.Remove(row)
        End If

こんな感じでどうでしょう?

引用返信 編集キー/
■90661 / inTopicNo.3)  Re[2]: DataGridView 最終行だけ処理回避したい
□投稿者/ ゆ牛 (5回)-(2019/04/02(Tue) 18:11:22)
返信ありがとうございます。

教えてくださったコードをC#に置き換えて試しましたが
やはり、最終よりひとつ上の行が消えてしまいます。
トレースしてみると row はひとつ上の内容を示しています。

DataGridViewRow row = dGView1.CurrentRow;
if (!row.IsNewRow)
{
    Debug.WriteLine(string.Format("row={0}", row)); // トレース
    dGView1.Rows.Remove(row);
}

クラスの仕様をもう一度調べてみることにします。
どうもありがとうございました。

引用返信 編集キー/
■90662 / inTopicNo.4)  Re[1]: DataGridView 最終行だけ処理回避したい
□投稿者/ 魔界の仮面弁士 (2135回)-(2019/04/02(Tue) 18:26:49)
2019/04/02(Tue) 18:32:38 編集(投稿者)

No90659 (ゆ牛 さん) に返信
> 最終行(空行)にカーソルがあるときに「削除」ボタンを押すと
> 最終よりひとつ上の行が消えてしまうようです。

もしかして、dGView1.DataSource にバインドした状態でしょうか?


行ヘッダーに三角マークが出る状態
  dGView1.RowHeadersVisible = true; // 行ヘッダー列を表示する
にしてアプリを実行し、末尾の新規行を選択した後に、
dGView1 以外のコントロールにフォーカスを移動してみてください。


データバインドしている際には、DataGridView がフォーカスを失った瞬間、
新規行ではなく最終行に CurrentRow が移動することになります。


private void dGView1_Leave(object sender, EventArgs e)
{
 if (dGView1.DataSource != null && dGView1.CurrentRow.IsNewRow)
 {
  // データバインドしている場合、新規行にいるときにフォーカスを喪失すると
  // 最終行に移動してしまうので、フォーカス喪失後に新規行に戻しておく
  BeginInvoke(new MethodInvoker(() => dGView1.CurrentCell = dGView1[dGView1.CurrentCellAddress.X, dGView1.NewRowIndex]));
 }
}


// 削除ボタンの処理
var row = dGView1.CurrentRow;
if (!row.IsNewRow)
{
 dGView1.Rows.Remove(row);
}
引用返信 編集キー/
■90664 / inTopicNo.5)  Re[2]: DataGridView 最終行だけ処理回避したい
□投稿者/ 魔界の仮面弁士 (2137回)-(2019/04/02(Tue) 19:11:53)
No90662 (魔界の仮面弁士) に追記
> private void dGView1_Leave(object sender, EventArgs e)
> {
>  if (dGView1.DataSource != null && dGView1.CurrentRow.IsNewRow)
>  {
>   // データバインドしている場合、新規行にいるときにフォーカスを喪失すると
>   // 最終行に移動してしまうので、フォーカス喪失後に新規行に戻しておく
>   BeginInvoke(new MethodInvoker(() => dGView1.CurrentCell = dGView1[dGView1.CurrentCellAddress.X, dGView1.NewRowIndex]));
>  }
> }


追記。


事前に範囲選択していた場合、上記実装だと CurrentCell プロパティを書き換えた時点で
選択状態が解除されてしまうので、わざわざ Leave イベントで対処しなくても済むような
DataGridView 派生クラスを用意してみました。


public class CustomDataGridView : DataGridView
{
  protected override void OnLeave(EventArgs e)
  {
    base.OnLeave(e);
    if (DataSource != null && CurrentRow.IsNewRow)
    {
        BeginInvoke(new MethodInvoker(() => SetCurrentCellAddressCore(CurrentCellAddress.X, NewRowIndex, false, false, false)));
    }
  }
}
引用返信 編集キー/
■90665 / inTopicNo.6)  Re[2]: DataGridView 最終行だけ処理回避したい
□投稿者/ ゆ牛 (6回)-(2019/04/02(Tue) 19:30:02)
返信ありがとうございます。

教えていただいたコードで期待する動作をするようになりました。

> もしかして、dGView1.DataSource にバインドした状態でしょうか?

「バインド」についてまだ理解不足ですが、
DataSetを用意し、その内容をdGView1のDataSourceとDataMemberプロパティへ
設定しています、このことでしょうか。
最初にこの説明をしておらず申し訳ありません。

> データバインドしている際には、DataGridView がフォーカスを失った瞬間、
> 新規行ではなく最終行に CurrentRow が移動することになります。

たしかに、「削除」ボタンをクリックすると
三角マークが新規行→最終行へ動くことが確認できました。
うまくいかなかった理由が呑み込めました。

> BeginInvoke(new MethodInvoker(() => dGView1.CurrentCell = dGView1[dGView1.CurrentCellAddress.X, dGView1.NewRowIndex]));

この処理の意味についてもこれから自習します。

どうもありがとうございました。


解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ