none
コンボボックス未選択でデータグリッドビューに空行が表示されてしまいます。 RRS feed

  • 質問

  • いつもお世話になっております。
    Vs2010 C# Pro + Windows7 Pro + PostgreSQLで開発してます。

    リレーションで連動させている2つのコンボボックス
    で絞り込んだデータを外部キーにしたDBからのデータをデータグリッドビューに表示させていますが
    Form_Load状態で(コンボボックスはまだ選択していない状態)
    データグリッドビューに空のレコードが一行表示されてしまいます。
    左側に三角印の空白状態のレコードです。米印の新規入力行とは別にという意味です。
    コンボボックスを選択して表示されたデータは一番下に新規入力行があり、正常に表示できています。
    なぜこのような状態になるのか、改善策どなたか教えてください。

    // リレーション作成
    ds.Relations.Add(new DataRelation("rel_ns",
    ds.Tables["numbers"].Columns["n_id"],
    ds.Tables["sector"].Columns["n_id"]));

    cmb_n_id.DataSource = ds;
    cmb_n_id.DisplayMember = "numbers.number";
    cmb_n_id.ValueMember = "numbers.n_id"; 

    cmb_s_id.DataSource = ds;
    cmb_s_id.DisplayMember = "numbers.rel_ns.sector";
    cmb_s_id.ValueMember = "numbers.rel_ns.s_id";
    cmb_s_id.SelectedIndexChanged += new EventHandler(cmb_s_id_SelectedIndexChanged);

    // bindingSourceRecordsを設定
    bindingSourceRecords.DataSource = ds;
    bindingSourceRecords.DataMember = "records";

    bindingNavigatorRecords.BindingSource = bindingSourceRecords;
    dataGridViewRecords.AutoGenerateColumns = false;
    dataGridViewRecords.DataSource = bindingSourceRecords;
    2011年2月5日 10:21

回答

  • このコードだけでは原因がわかりませんが、recordsテーブルをどのタイミングでどのように作成されているのかが問題であるように思います。たぶん、初期状態でrecordsテーブルに1行レコードが存在しているのではないでしょうか? recordsテーブルをFillするところを中心に調査されると良いと思います。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク oira3ryu 2011年2月6日 1:03
    2011年2月5日 11:24
    モデレータ

すべての返信

  • このコードだけでは原因がわかりませんが、recordsテーブルをどのタイミングでどのように作成されているのかが問題であるように思います。たぶん、初期状態でrecordsテーブルに1行レコードが存在しているのではないでしょうか? recordsテーブルをFillするところを中心に調査されると良いと思います。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク oira3ryu 2011年2月6日 1:03
    2011年2月5日 11:24
    モデレータ
  • trapemiyaさん、いつもありがとうございます。

    どうしてこうなるのかは私には説明できないのですが

    // before

    bindingNavigatorRecords.BindingSource = bindingSourceRecords;

    dataGridViewRecords.AutoGenerateColumns = false;

    dataGridViewRecords.DataSource = bindingSourceRecords;

     

    // after

    bindingNavigatorRecords.BindingSource = bindingSourceRecords;

    dataGridViewRecords.AutoGenerateColumns = false;

    dataGridViewRecords.DataSource = ds;

    データグリッドビューのデータソースをバインディングソースにしていたからのようです。

    データグリッドビューのデータソースをデータセットにすることで解決できました。

    bindingSourceRecords.DataSource = ds;

    根本は同じdsをデータソースにしていてもこのような動作になるのですね。

    2011年2月6日 1:17
  • どうしてこうなるのかは私には説明できないのですが

    おかしいですね? 私にも説明できず、疑問に思いましたので私の方でコードを想像しながらテストしてみましたが、BindingSourceでも問題なく実行されました。
    dsの場合も同様に実行されましたが、DataMemberでテーブル名を新たに指定する必要がありました。

    基本的にはBindingSourceでも問題ありませんので、何かが影響しているのだと思います。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2011年2月7日 0:35
    モデレータ
  • >Form_Load状態で(コンボボックスはまだ選択していない状態)

    恐らく、Form_Loadの時にコンボックスの条件なしの状態で検索されているのではないでしょうか?

    コンボボックスの初期設定値(selectedIndexなど)はどのようになっているのでしょうか?

     

    対策としては、DataGridViewをはじめはVisible = falseなどにして、コンボボックスが選択された状態でVisible = trueにするなどいかがでしょう。

    もしくはdataSource = nullなど。

     

     

    2011年2月7日 6:22
  • 朴智星さん、ありがとうございます。
    Form_Loadでは、以下のように設定しています。
    こうではなくて、具体的に値を設定することが必要なのでしょうか?

                da.SelectCommand = new NpgsqlCommand
                (
                       "select"
                    + " r_id"
                    + ", id"
                    + ", s_id"
                    + ", results"
                    + ", flg"
                    + ", time_stamp"
                    + ", n_id"
                    + " from"
                    + " records"
                    + " where n_id=:n_id"
                    + " and s_id=:s_id"
                    + " order by r_id",
                    m_conn
                );
                if (cmb_n_id.SelectedItem == null)
                {
                    // SelectedItemがない場合
                    da.SelectCommand.Parameters.Add(new NpgsqlParameter("n_id",
                    NpgsqlTypes.NpgsqlDbType.Integer, 0, "n_id",
                    ParameterDirection.Input, false, 0, 0, DataRowVersion.Current,
                    DBNull.Value));
                }
                else
                {
                    // SelecteItemがある場合
                    DataRowView row = (DataRowView)cmb_n_id.SelectedItem;
                    da.SelectCommand.Parameters.AddWithValue("n_id", row["n_id"]);
                }
                if (cmb_s_id.SelectedItem == null)
                {
                    // SelectedItemがない場合
                    da.SelectCommand.Parameters.Add(new NpgsqlParameter("s_id",
                    NpgsqlTypes.NpgsqlDbType.Integer, 0, "s_id",
                    ParameterDirection.Input, false, 0, 0, DataRowVersion.Current,
                    DBNull.Value));
                }
                else
                {
                    // SelecteItemがある場合
                    DataRowView row = (DataRowView)cmb_s_id.SelectedItem;
                    da.SelectCommand.Parameters.AddWithValue("s_id", row["s_id"]);
                }

    >対策としては、DataGridViewをはじめはVisible = falseなどにして、コンボボックスが選択された状態でVisible = trueにするなどいかがでしょう。

    >もしくはdataSource = nullなど。

    これは、まだ試していないのでやってみようと思います。

    2011年2月7日 23:07
  • trapemiyaさん、ありがとうございます。

    >基本的にはBindingSourceでも問題ありませんので、何かが影響しているのだと思います。

    そうですか、もう少し調べてみます。

    2011年2月7日 23:09
  • DataGridViewを描画するタイミングがポイントになると思います。

    上記の分岐につきましては、コンボボックスが2つともに選択された状態である場合にのみ描画するの条件がいいと思います。

    また、コンボボックスにつきましては、コンストラクタで設定してselectedIndexを1などに指定しておけば、常に選択されている状態になります。

    その場合は、上記の分岐が必要なくなります。(選択項目にnullを入れた場合はその限りではありませんが)

    考慮事項といたしましては、n_id,s_idがnullという条件が実際のrecordsテーブルに存在するか、です。

    あと、気になった点では、コンボボックスの片方にだけSelectedIndexChangeイベントがあるというところでしょうか。

    両方入れて、双方でDataGridViewを描画するメソッドを呼ぶようにしてあげたらいいのか、と。

    2011年2月8日 1:08