- PR -

WinForm上のDataGridで最後の行を削除するとIndexOutOfRangeExceptionが発生

1
投稿者投稿内容
om(takanao)
会議室デビュー日: 2002/06/19
投稿数: 16
投稿日時: 2003-12-16 17:19
Windows Form上にDataGridを配置して、ボタンをクリックされたら
現在の行を削除するプログラムを作成しています。

この際、最後の行を選択してボタンをクリックするとIndexOutOfRangeExceptionが発生します。
データソースにはArrayListを使用しています。
なにか回避策がございましたら教えてください。

再現する最小のサンプルを作成しました。
private ArrayList ar = new ArrayList();
private void Form1_Load(object sender, System.EventArgs e)
{
ar.Add(new c(0,"a"));
ar.Add(new c(1,"b"));
ar.Add(new c(2,"c"));
BindToGrid();
}
private class c
{
int _i;
string _s;
public int i{get{return _i;}}
public string s{get{return _s;}}
public c(int i, string s)
{
_i = i; _s = s;
}
}
private void BindToGrid()
{
dataGrid1.DataSource = null;
dataGrid1.Refresh();
dataGrid1.Update();
dataGrid1.DataSource = ar;
dataGrid1.Refresh();
dataGrid1.Update();
}
private void button1_Click(object sender, System.EventArgs e)
{
c myc;
myc = (c)ar[dataGrid1.CurrentCell.RowNumber];
ar.Remove(myc);
BindToGrid();
}
Jubei
ぬし
会議室デビュー日: 2002/03/02
投稿数: 830
お住まい・勤務地: 関西
投稿日時: 2003-12-16 17:54
こんにちわ。諸農です。

引用:

YOSHIさんの書き込み (2003-12-16 17:19) より:

この際、最後の行を選択してボタンをクリックするとIndexOutOfRangeExceptionが発生します。
データソースにはArrayListを使用しています。
なにか回避策がございましたら教えてください。



dataGrid1.CurrentCell.RowNumberと
ArrayListの要素数との同期が取れていないのではないですか?
というか、NULL行はまだArrayListには反映されていないんですよね??

回避策として考えられるのは、選択されているセルのRowNumberが
配列範囲外かどうかをチェックすることだと思いますが。。

論点が違っているようでしたら、ご容赦をm(__)m

ではでは(^^)/
_________________
諸農和岳
Powered by Turbo Delphi & Microsoft Visual Studio 2005

十兵衛@わんくま同盟
http://blogs.wankuma.com/jubei/
om(takanao)
会議室デビュー日: 2002/06/19
投稿数: 16
投稿日時: 2003-12-16 18:09
こんにちはYOSHIです。

引用:

dataGrid1.CurrentCell.RowNumberと
ArrayListの要素数との同期が取れていないのではないですか?
というか、NULL行はまだArrayListには反映されていないんですよね??


ちょっと違います。
ArrayListの最後のアイテムを削除してそれをDataGridにバインドしています。
なので、普通に考えるとArrayListとDataGridの同期は取れていると思います。
ところが、(たぶん)DataGridの内部に持っているRowNumberが以前の値を
保持していて、この例外が発生しているのだと思います。
Jubei
ぬし
会議室デビュー日: 2002/03/02
投稿数: 830
お住まい・勤務地: 関西
投稿日時: 2003-12-17 16:39
こんにちわ。諸農です。

引用:

YOSHIさんの書き込み (2003-12-16 18:09) より:

ArrayListの最後のアイテムを削除してそれをDataGridにバインドしています。
なので、普通に考えるとArrayListとDataGridの同期は取れていると思います。
ところが、(たぶん)DataGridの内部に持っているRowNumberが以前の値を
保持していて、この例外が発生しているのだと思います。



アップされていたコードを試してみました。
思いっきりはずしていましたですね。すみません。

対応は次のようなコードになると思います。

コード:
private ArrayList ar = new ArrayList();
private class c
{
    int _i;
    string _s;
    public int i{get{return _i;}}
    public string s{get{return _s;}}
    public c(int i, string s)
    {
        _i = i; _s = s;
    }
}
private void Form_Load(object sender, System.EventArgs e)
{
    ar.Add(new c(0,"a"));
    ar.Add(new c(1,"b"));
    ar.Add(new c(2,"c"));
    dataGrid1.DataSource = ar;
    DataGridTableStyle ts = new DataGridTableStyle();
    ts.MappingName = "ArrayList";
    DataGridTextBoxColumn[] cs = new DataGridTextBoxColumn[2];
    cs[0] = new DataGridTextBoxColumn();
    cs[0].MappingName = "i";
    cs[0].HeaderText = "数字";
    cs[1] = new DataGridTextBoxColumn();
    cs[1].MappingName = "s";
    cs[1].HeaderText = "文字列";
    ts.GridColumnStyles.AddRange(cs);
    dataGrid1.TableStyles.Clear();
    dataGrid1.TableStyles.Add(ts);
}
private void button1_Click(object sender, System.EventArgs e)
{
    CurrencyManager cm = (CurrencyManager)dataGrid1.BindingContext[ar];
    cm.RemoveAt(cm.Position);
    cm.Refresh();
}



CurrencyManagerを使って、Refresh()するところがミソかもしれません。

ではでは(^^)/
_________________
諸農和岳
Powered by Turbo Delphi & Microsoft Visual Studio 2005

十兵衛@わんくま同盟
http://blogs.wankuma.com/jubei/
om(takanao)
会議室デビュー日: 2002/06/19
投稿数: 16
投稿日時: 2003-12-17 19:03
諸農さん。うまくいきました!ありがとうございます!

CurrencyManager。未知のクラスでした。
1

スキルアップ/キャリアアップ(JOB@IT)