DOBON.NETプログラミング道掲示板

■34190 / 5階層)  ListBoxにデータが表示されない
□投稿者/ 魔界の仮面弁士 大御所(1218回)-(2019/03/08(Fri) 22:31:21)
  • アイコン2019/03/08(Fri) 23:23:18 編集(投稿者)

    No34189に返信(ケミカルさんの記事)
    > //普通のDataTable
    > DataTable dataTable1 = new DataTable();
    > //型付データセット
    > DataTable dataTable2 = new DataSet().Table;

    なるほど、データセットクラス名が "DataSet" なんですね。
    ちょっと混乱してしまいました。(^^;

    System.Data 名前空間の DataSet なのか
    WindowsFormsApplication1 名前空間の DataSet なのか
    分かりにくくなるので、混同されないような名前付けをお奨めします


    結論から言えば、最初の回答でも述べた通り、
    『インスタンス管理』に問題があったようです。

    これは要するに、
     example.FillData(dataTable2);
    という操作と
     dataTable2 = example.GetData();
    という操作の違いです。


    前者は、既存の DataTable インスタンスを渡して、
    その器にデータを埋め込んでもらう処理。

    後者はデータの入った新しい DataTable インスタンスを作ってもらい、
    その新しい器を戻り値として受け取る処理です。


    では、提示頂いたコードで見てみましょう。

    > DataTable dataTable1 = new DataTable();
    > DataTable dataTable2 = new DataSet().Table;

    フィールド変数の dataTable1/2 には、new Form1() されたと同時に、
    DataTable のインスタンスが new されて保持されます。
    ここまでは良いですよね?


    > //ListBox2に新しくデータをセットする
    > private void button2_Click_1(object sender, EventArgs e)
    > {
    >  var strSql = @"SELECT * FROM T where col1 = 'Y'";
    >  dataTable2.Clear();
    そしてここで Clear しているのも、同じ器に対する操作です。
    ここまでは問題ありません。


    >  dataTable2 = DoSomething.selectSQL(strSql);
    問題はここ。

    dataTable2 が持っていた古いインスタンスは捨てられて、
    selectSQL から得た別のインスタンスへの参照に置き換えられています。

    この場合は本来、
     var newTbl = DoSomething.selectSQL(strSql);
     dataTable2.Merge(dataTable2, true);
    などとした方が良いでしょう。

    あるいは『DoSomething.FillBySQL(dataTable2, strSql);』となるような
    メソッドを用意するのもお奨めです。



    >  listBox2.DataSource = dataTable2;
    >  listBox2.DisplayMember = "column1";
    > }
    上記のバインド操作は Form1_Load で既に行っていますので、
    本来であれば、あらためてバインドし直す必要はありませんでした。

    しかし現状、再バインドが必要になってしまっているのは、
    同一の器(DataTable インスタンス)を使いまわしているのではなく、
    データを取得するたびに、新しい器を生成してしまっているためです。

    器が変わったので、ListBox のバインド先も切り替えねばならなかったという罠。


    もしも器を使いまわさず、毎回作り直すことを想定しているのなら、
    そもそも事前の Clear は冗長であり無意味です。

     // dataTable2.Clear();
     dataTable2 = DoSomething.selectSQL(strSql);
     listBox2.DataSource = dataTable2;
     listBox2.DisplayMember = "column1";



    個人的には、同じインスタンスを使いまわす実装にすることをお奨めします。
    バインド先を変更すると、ListBox の選択状態もリセットされてしまいますしね。



    > //普通のDataTable
    > DataTable dataTable1 = new DataTable();
    > //型付データセット
    > DataTable dataTable2 = new DataSet().Table;

    ところで上記のコード。

    折角の型付きなのですから、後者は本来
     DataSet.TableDataTable dataTable2 = new DataSet().Table;
    となるものです。

    提示頂いたコードの場合、名前空間を省略せずに記載すると
     global::System.Data.DataTable dataTable1 = new global::System.Data.DataTable();
     global::System.Data.DataTable dataTable2 = new global::WindowsFormsApplication1.DataSet().Table;
     //global::WindowsFormsApplication1.DataSet.TableDataTable dataTable2 = new global::WindowsFormsApplication1.DataSet().Table;
    という意味になり、型付きのメリットが半減してしまいそう。

    現状では、DoSomething 側も型付を意識した設計にはなっていないので、
    型付きではない DataTable で受けるしかなかったのでしょうけれども、
    今回提示した形で修正すれば、型付の方で扱えるようになると思います。
違反を報告
削除キー/

前の記事(元になった記事) 次の記事(この記事の返信)
←Re[4]: ListBoxにデータが表示されない /ケミカル →Re[6]: ListBoxにデータが表示されない /ケミカル
 
上記関連ツリー

Nomalアイコン ListBoxにデータが表示されない / ケミカル (19/03/07(Thu) 11:46) #34184
Nomalアイコン Re[1]: ListBoxにデータが表示されない / 魔界の仮面弁士 (19/03/07(Thu) 12:04) #34185
  └Nomalアイコン Re[2]: ListBoxにデータが表示されない / ケミカル (19/03/07(Thu) 16:40) #34186
    └Nomalアイコン Re[3]: ListBoxにデータが表示されない / 魔界の仮面弁士 (19/03/07(Thu) 17:34) #34187
      └Nomalアイコン Re[4]: ListBoxにデータが表示されない / ケミカル (19/03/08(Fri) 18:11) #34189
        └Nomalアイコン ListBoxにデータが表示されない / 魔界の仮面弁士 (19/03/08(Fri) 22:31) #34190 ←Now
          └Nomalアイコン Re[6]: ListBoxにデータが表示されない / ケミカル (19/03/11(Mon) 18:21) #34192 解決み!

All 上記ツリーを一括表示 / 上記ツリーをトピック表示
 
上記の記事へ返信

Mode/  Pass/


- Child Tree -