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

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

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.11551 の関連記事表示

<< 0 >>
■11551  DataGridでの例外回避
□投稿者/ シャノン -(2007/12/17(Mon) 20:13:38)

    分類:[.NET 全般] 

    2007/12/17(Mon) 20:16:43 編集(投稿者)

    お世話になります。
    何かいい案があればご教示ください。

    VS.NET 2003 + C# でクラサバアプリを作っています。
    忌まわしき DataGrid での悩みです。

    DB から取ってきたデータを、ごにょごにょ加工して、
    DataGrid にバインドしてあるテーブルに追加しています(※)
    (DB から取ってきた生データを持っているテーブルを直接バインドしていません)。

    DataGrid は実際には DataGrid 派生クラスでして、
    行が選択されたことをイベントとして検出するために、
    DataGrid.ListManager.CurrentChanged をハンドリングして、
    自前で実装した SelectedItemChanged イベントを発生させています。
    SelectedItemChanged イベントの中では、選択された行を
    取得するために、やはり実装した SelectedItem プロパティを取得しています。

    SelectedItem プロパティのコードはこんな感じです。

    public object SelectedItem
    {
    get
    {
    if( this.ListManager == null )
    {
    return null;
    }

    if( this.ListManager.Count == 0 ||
    this.ListManager.Position == -1 ||
    ! this.IsSelected( this.ListManager.Position ) )
    {
    return null;
    }

    return this.ListManager.Current;
    }
    }

    で、※部分では、DBから取得した行を一行ずつループして、
    表示用に加工しつつ、バインドしてある表示用テーブルに追加しています。
    ここでは、表示用テーブル.Rows.Add を使っているのですが、
    これをやると、一行追加するごとに、DataGrid 派生クラスの
    ListManager.CurrentChanged が発生し、イベントハンドラ中で
    SelectedItem が取得されます。
    その際、バインドされているテーブルにはデータが追加されているが、
    DataGrid 側にはまだ反映されていないタイミングで処理が走ると思われ、
    ListManager.Count が 0 でないにもかかわらず、
    IsSelected( 0 ) で OutOfRangeException が発生してしまいます。

    IsSelected を使わなければ例外は出ないのですが、その場合、
    選択色になっていないがアクティブな行(グリッドの左端に三角がついている行)
    も取得してしまいます。
    これを、選択状態になければ取得しないようにしたいので、IsSelected
    で判定しています。

    突っ込みどころがたくさんあるような気がして、あえて焦点をぼかした
    質問にしてみました。
    例外が出ないようにするにはどうしたらいいでしょう? 以前の問題として
    おかしいところがあったらご指摘ください。
    ただし、あまりに根本的過ぎる問題は対処できない可能性が大きいですorz
親記事 /過去ログ25より / 関連記事表示
削除チェック/

■11607  Re[1]: DataGridでの例外回避
□投稿者/ れい -(2007/12/18(Tue) 22:11:44)
    No11551 (シャノン さん) に返信
    > 突っ込みどころがたくさんあるような気がして、あえて焦点をぼかした
    > 質問にしてみました。
    > 例外が出ないようにするにはどうしたらいいでしょう? 以前の問題として
    > おかしいところがあったらご指摘ください。

    一見よさげなのに、なんかうまくいかないということは、
    おそらく根本的な方針が間違ってるのだと思うのですが、
    使わなくなって久しいので、
    もうぜんぜん覚えてないです。

    で、無責任に言うと。

    ぼんやり覚えてるところによると、
    CurrencyManager.Positionはダメで、
    DataGrid.CurrentRowIndexを使うのがよかったのではないかと思います。
    試してませんが。

    あと、できればミニマムコードがあるといいのではないかと。

    #私はVS2008導入に伴い、VS2003は消してしまいました。
    #2.0でも同じ問題が発生しそうな気がしますので、
    #ミニマムコードがあれば試すくらいはできるかなぁ。
記事No.11551 のレス /過去ログ25より / 関連記事表示
削除チェック/

■11736  Re[2]: DataGridでの例外回避
□投稿者/ シャノン -(2007/12/20(Thu) 17:23:26)
    No11607 (れい さん) に返信

    お返事ありがとうございます。

    > ぼんやり覚えてるところによると、
    > CurrencyManager.Positionはダメで、
    > DataGrid.CurrentRowIndexを使うのがよかったのではないかと思います。
    > 試してませんが。

    ダメでした。
    DataGridに行が一行もないとき、CurrentRowIndexは0になります。
    この状態でIsSelected(0)すると落ちてしまいます。

    > あと、できればミニマムコードがあるといいのではないかと。

    こちらにupしました。
    http://www.technoledge.info/DGMin.zip

    よろしくお願いいたします。
記事No.11551 のレス /過去ログ25より / 関連記事表示
削除チェック/

■11753  Re[3]: DataGridでの例外回避
□投稿者/ れい -(2007/12/20(Thu) 23:54:20)
    No11736 (シャノン さん) に返信
    > こちらにupしました。
    > http://www.technoledge.info/DGMin.zip
    
    ちょっとずつ思い出してきました。
    
    ・DataGridはCurrencyManagerのイベントを使って自分を更新している。
    ・現在の位置が変わったときCurrencyManagerはCurrentChangedで通知する。
    ・イベントハンドラは呼び出される順序が保証できない。
    
    なので、CurrencyManagerのイベント処理をしてる最中に
    DataGridの関連するプロパティをいじると、おかしくなります。
    イベントハンドラの追加順とかで動かなくなったり。
    私のところではIsSelectedもちゃんと動きませんでした。
    
    CurrentChangedやPositionChangedイベント終了後に呼ばれるイベントがあればいいのですが、
    CurrencyManagerにはありません。
    
    DataGrid自身が出すイベント、CurrentCellChangedを使うのが順当かと思いましたが、
    CurrentCellChangedイベント終了後に行がSelectされるため、IsSelectedが使えません。
    
    ならDataGridにそういったイベントがあるのかと探すと、MouseDownとかKeyDownとかを使うしかない。
    ためしに作ったら一応動いてはいますが、
    本当に全部うまく動くのか確信が持てない所が問題です。
    
    結局、DataGridはSelectedが変わったときにイベントを投げない仕様なので、
    SelectedItemChangedを自分で実装するのは困難であるということになります。
    CurrentCellChangedはきちんと動くので、セル単位で処理せよということでしょう。
    
    イベントドリブンで設計がダメだとこういうことになるんですよね。
    やっぱりDataGridは嫌いだ。
    
    一応、なんとなく動いてるものを書いときます。
    
        class DataGridEx : DataGrid
        {
            private int _selectedindex = -1;
            public event EventHandler SelectedItemChanged;
            protected override void OnMouseDown(MouseEventArgs e)
            {
                base.OnMouseDown(e);
                CheckSelectedIndex();
            }
            protected override void OnMouseMove(MouseEventArgs e)
            {
                base.OnMouseMove(e);
                CheckSelectedIndex();
            }
            protected override void OnKeyDown(KeyEventArgs ke)
            {
                base.OnKeyDown(ke);
                CheckSelectedIndex();
            }
            protected override bool ProcessDialogKey(Keys keyData)
            {
                bool r = base.ProcessDialogKey(keyData);
                CheckSelectedIndex();
                return r;
            }
            protected override bool ProcessKeyPreview(ref Message m)
            {
                bool r = base.ProcessKeyPreview(ref m);
                CheckSelectedIndex();
                return r;
            }
            public object SelectedItem
            {
                get
                {
                    if (_selectedindex < 0) return null;
                    return this.ListManager.List[_selectedindex];
                }
            }
    
            private void CheckSelectedIndex()
            {
                int newindex;
                if (this.ListManager == null) newindex = -1;
                else if (this.ListManager.Count == 0) newindex = -1;
                else if (this.ListManager.Position == -1) newindex = -1;
                else if (!this.IsSelected(this.ListManager.Position)) newindex = -1;
                else newindex = this.ListManager.Position;
                if (_selectedindex == newindex) return;
                _selectedindex = newindex;
                if (SelectedItemChanged != null) SelectedItemChanged(this, EventArgs.Empty);
            }
        }
    
記事No.11551 のレス /過去ログ25より / 関連記事表示
削除チェック/

■11791  Re[4]: DataGridでの例外回避
□投稿者/ シャノン -(2007/12/21(Fri) 12:15:09)
    No11753 (れい さん) に返信

    ありがとうございます。

    > 私のところではIsSelectedもちゃんと動きませんでした。

    IsSelected「も」と言うより、まさに IsSelected が問題なのです。

    > ならDataGridにそういったイベントがあるのかと探すと、MouseDownとかKeyDownとかを使うしかない。
    > ためしに作ったら一応動いてはいますが、
    > 本当に全部うまく動くのか確信が持てない所が問題です。

    ですねぇ。

    > イベントドリブンで設計がダメだとこういうことになるんですよね。
    > やっぱりDataGridは嫌いだ。

    というよりも、セル単位用に設計されているものを行単位で利用しようとしているのがダメなんでしょうね。
    行単位選択にして、読み取り専用にして、CtrlやShiftで複数選択可能にして、行の背景色を変えられるようにして、Tabキーでセル間遷移しないようにして…実際には山ほどカスタマイズして使ってます。もう手放したいorz
    ただ、行単位Gridって需要あると思うのに、標準で提供してくれていなかったという点では、やっぱり嫌いです。
    2.0のDataGridViewは使いやすいんでしょうか…気になります。

    > 一応、なんとなく動いてるものを書いときます。

    ありがとうございます。参考にさせていただきます。

    # ミニマムソースは削除しました。
記事No.11551 のレス / END /過去ログ25より / 関連記事表示
削除チェック/

■11793  Re[5]: DataGridでの例外回避
□投稿者/ れい -(2007/12/21(Fri) 12:26:04)
    No11791 (シャノン さん) に返信
    >>イベントドリブンで設計がダメだとこういうことになるんですよね。
    >>やっぱりDataGridは嫌いだ。
    >
    > というよりも、セル単位用に設計されているものを行単位で利用しようとしているのがダメなんでしょうね。

    んー。これが微妙で。セルなのか行なのか、不明です。

    CurrencyManagerは行単位で動きます。
    DataGridだって、行ヘッダーがあり、削除は行ごとです。
    DataGrid内部は行ごとにできてるっぽいのに、
    イベントはセル単位しかなく、プロパティもセル単位。
    なのにIsSelectedは行単位。

    統一の取れてないだめな設計だと思います。
    AccessとかVB6とかの影響を悪く受けてる気がします。

    行単位で選択できるものなら、
    変更があったときにイベントを投げるように作っておくべきなのに。

    > 2.0のDataGridViewは使いやすいんでしょうか…気になります。

    はるかにまし、というか、良いです。戻れません。
    でもまだ気になるところはあるかなぁ。
記事No.11551 のレス /過去ログ25より / 関連記事表示
削除チェック/

■11794  Re[6]: DataGridでの例外回避
□投稿者/ シャノン -(2007/12/21(Fri) 12:33:16)
    2007/12/21(Fri) 12:43:30 編集(投稿者)

    No11793 (れい さん) に返信

    >>というよりも、セル単位用に設計されているものを行単位で利用しようとしているのがダメなんでしょうね。
    >
    > んー。これが微妙で。セルなのか行なのか、不明です。

    もう一次元ありますよ。
    DataGridは1つのコントロールで複数のテーブルを扱えます。
    その時にIsSelectedがどう振舞うのかは試していません。
    というか、複数テーブルなんて使ってる人がいるのか疑問です。

    >>2.0のDataGridViewは使いやすいんでしょうか…気になります。
    >
    > はるかにまし、というか、良いです。戻れません。
    > でもまだ気になるところはあるかなぁ。

    いいなぁ…
記事No.11551 のレス / END /過去ログ25より / 関連記事表示
削除チェック/

■11796  Re[7]: DataGridでの例外回避
□投稿者/ れい -(2007/12/21(Fri) 12:39:40)
    No11794 (シャノン さん) に返信
    > もう一次元ありますよ。

    ぐはっ

    忘れてた。
記事No.11551 のレス /過去ログ25より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -