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

ツリー一括表示

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アイコン Re[5]: ListBoxにデータが表示されない /魔界の仮面弁士 (19/03/08(Fri) 22:31) #34190
          └Nomalアイコン Re[6]: ListBoxにデータが表示されない /ケミカル (19/03/11(Mon) 18:21) #34192 解決み!


親記事 / ▼[ 34185 ]
■34184 / 親階層)  ListBoxにデータが表示されない
□投稿者/ ケミカル 一般人(1回)-(2019/03/07(Thu) 11:46:23)
  • アイコン環境/言語:[c# vs2015] 
    分類:[.NET] 

    ListBox1、ListBox2というListBoxが2つあり、それぞれのDataSourceがDataTableになっています。

    ListBox1.DataSource = dataTable1
    ListBox2.DataSource = dataTable2

    ボタンを押すと、ListBox1に表示されているデータがListBox2に移るようにプログラムを組んでいます。

    お伺いしたいのは、

    dataTable2.cleear();をした後にボタンを押してもListBox2にデータが何も表示されません。
    dataTable2の中身を確認すると、正しくdataTable2に保存されていあました。
    ListBox2にデータが表示されるようにするにはどうしたらいいでしょうか?
違反を報告
[ □ Tree ] 返信 削除キー/

▲[ 34184 ] / ▼[ 34186 ]
■34185 / 1階層)  Re[1]: ListBoxにデータが表示されない
□投稿者/ 魔界の仮面弁士 大御所(1216回)-(2019/03/07(Thu) 12:04:58)
  • アイコン
    No34184に返信(ケミカルさんの記事)
    > dataTable2.cleear();をした後にボタンを押してもListBox2にデータが何も表示され
    cleear というのは
    Clear のことでしょうか。
    
    dataTable2.Rows.Clear(); ではなく
    dataTable2.Clear(); ということは、
    型付 DataSet をお使いでしょうか。
    
    
    > ListBox2にデータが何も表示されません。
    DataSource のインスタンスが指し変わっていることは無いでしょうか。
    
    当方で下記のコードをテストしてみましたが、button2 押下時に
    listBox2 の内容が変化していました。(VS2017 + .NET 3.5 で確認)
    
    
    
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    
        DataTable dataTable1;
        DataTable dataTable2;
        private void Form1_Load(object sender, EventArgs e)
        {
            dataTable1 = new DataSet("DataSet1").Tables.Add("DataTable1");
            dataTable2 = new DataSet("DataSet1").Tables.Add("DataTable1");
            dataTable1.Columns.Add("DataColumn1");
            dataTable2.Columns.Add("DataColumn1");
    
            dataTable1.Rows.Add("aaa");
            dataTable1.Rows.Add("bbb");
            dataTable1.Rows.Add("ccc");
            dataTable1.AcceptChanges();
    
            dataTable2.Rows.Add("xxx");
            dataTable2.AcceptChanges();
    
            listBox1.DataSource = dataTable1;
            listBox1.DisplayMember = "DataColumn1";
            listBox2.DisplayMember = "DataColumn1";
            listBox2.DataSource = dataTable2;
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
            dataTable2.Rows.Clear();
        }
    
        private void button2_Click(object sender, EventArgs e)
        {
            dataTable2.Rows.Add("TEST" + DateTime.Now.Ticks);
        }
    }

違反を報告
[ 親 34184 / □ Tree ] 返信 削除キー/

▲[ 34185 ] / ▼[ 34187 ]
■34186 / 2階層)  Re[2]: ListBoxにデータが表示されない
□投稿者/ ケミカル 一般人(2回)-(2019/03/07(Thu) 16:40:43)
  • アイコン
    dataTable2.Rows.Clear(); ではなくdataTable2.Clear(); でした。失礼しました。
    型付DataSetです。そして、dataTable2.Clear();のせいで希望通りの動きにならないと
    思っていましたが間違いでした。これは問題ありませんでした。
    
    問題になっているのは、追記しました「button3」の箇所でした。
    データベースに問合せをして、データが存在していれば、引き続き
    button2を押しても正しくdataTable2にデータが追加されListBox2にもデータが表示されていました。
    
    しかし、データベースにデータがなかった場合、button2を押すと
    dataTable2にはデータは追記されるものの(ブレイクポイントを設定して中身を見ています)、
    ListBox2には値が表示されませんでした。
    
    using System;
    using System.Data;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            DataTable dataTable1;
            DataTable dataTable2;
            private void Form1_Load(object sender, EventArgs e)
            {
                dataTable1 = new DataSet("DataSet1").Tables.Add("DataTable1");
                dataTable2 = new DataSet("DataSet1").Tables.Add("DataTable1");
                dataTable1.Columns.Add("DataColumn1");
                dataTable2.Columns.Add("DataColumn1");
    
                dataTable1.Rows.Add("aaa");
                dataTable1.Rows.Add("bbb");
                dataTable1.Rows.Add("ccc");
                dataTable1.AcceptChanges();
    
                dataTable2.Rows.Add("xxx");
                dataTable2.AcceptChanges();
    
                listBox1.DataSource = dataTable1;
                listBox1.DisplayMember = "DataColumn1";
                listBox2.DisplayMember = "DataColumn1";
                listBox2.DataSource = dataTable2;
            }
    
            private void button1_Click_1(object sender, EventArgs e)
            {
                dataTable2.Rows.Clear();
            }
    
            private void button2_Click_1(object sender, EventArgs e)
            {
                dataTable2.Rows.Add("TEST" + DateTime.Now.Ticks);
            }
    
            private void button3_Click(object sender, EventArgs e)
            {
                //DB接続部分省略
                var strSQL = "select * from table where col = '100'";
    
                using (SQLCommand command = new SQLCommand(sql, connection))
                {
                    using (SQLDataAdapter adp = new SQLDataAdapter())
                    {
                        adp.SelectCommand = command;
                        adp.Fill(dataTable2);
                    }
                }
            }
        }
    }
    

違反を報告
[ 親 34184 / □ Tree ] 返信 削除キー/

▲[ 34186 ] / ▼[ 34189 ]
■34187 / 3階層)  Re[3]: ListBoxにデータが表示されない
□投稿者/ 魔界の仮面弁士 大御所(1217回)-(2019/03/07(Thu) 17:34:07)
  • アイコン2019/03/08(Fri) 23:35:48 編集(投稿者)

    No34186に返信(ケミカルさんの記事)
    > dataTable2.Rows.Clear(); ではなくdataTable2.Clear(); でした。失礼しました。

    ということは、型付 DataSet であることになりますね。

    <追記>
    ごめんなさい。何か勘違いしていたようです。
    型付きかどうかに関わらず、
     dataTable2.Clear();
     dataTable2.Rows.Clear();
    のいずれの構文も使えるのでした。
    (厳密には異なる処理だが、ほぼ同じ結果になる)
    </追記>


    > 型付DataSetです。

    型付 DataSet ではあるけれど、データの取得には
    TableAdapter を用いておらず、
    DataAdapter を使っているのでしょうか?


    > using (SQLCommand command = new SQLCommand(sql, connection))
    SQLCommand というのは、
    SqlCommand のことでしょうか?
    (System.Data.SqlClient.SqlCommand クラス)



    > 問題になっているのは、追記しました「button3」の箇所でした。

    う〜ん。まだ食い違いがあるような…。

    新たに提示いただいたコードだと、私のコードそのままに、
    > DataTable dataTable2;
    のように、「型付ではない System.Data.DataTable」型の変数が使われています。

    型付 DataSet だというのであれば、変数宣言は
     DataSet1.DataTable1DataTable dataTable1;
     DataSet1.DataTable1DataTable dataTable2;
    のようになるはずですし、インスタンス生成も
     dataTable1 = new DataSet1().DataTable1; // dataTable1.DataSet != null にする場合
     dataTable2 = new DataSet1.DataTable1DataTable(); // dataTable2.DataSet == null にする場合
    などとなっているはず…。


    > //DB接続部分省略
    「adp.Fill(dataTable2);」 の前に dataTable2 をクリアする処理がありませんね。

    手元の環境で試してみましたが、button1 を押さずに button3 を何度も押した場合、
    データが無ければ、listBox2 の内容は変化しません。(増加も減少もしない)

    データが存在していた場合は、ボタンを押すたびに、
    listBox2 の行数がどんどん増えていきました。
    (DataTable に PrimaryKey 制約がある場合は、もちろんエラーになります)


    > dataTable2にはデータは追記されるものの(ブレイクポイントを設定して中身を見ています)、
    > ListBox2には値が表示されませんでした。

    前回の回答の繰り返しになってしまいますが、
    Form1_Load で listBox2.DataSource に割り当てた「dataTable2 変数」が持つインスタンスと、
    button3_Click で adp.Fill した際の「dataTable2 変数」」が持つインスタンスが、
    別のオブジェクトになっている可能性はありませんか?
違反を報告
[ 親 34184 / □ Tree ] 返信 削除キー/

▲[ 34187 ] / ▼[ 34190 ]
■34189 / 4階層)  Re[4]: ListBoxにデータが表示されない
□投稿者/ ケミカル 一般人(3回)-(2019/03/08(Fri) 18:11:29)
  • アイコン
    何度もすいません。実際のコードは下記にあるような感じになっています。
    Load時にデータベースにはデータがあるものとして、ListBox1にはデータが
    表示されます。
    
    @こちらは正しく動きます。
    ・Button1を実行
    ・Button2を実行(データベースにデータが存在する場合、ListBox2にデータが表示される)
    ・Button1を実行
    ・ListBox2に追加でデータが表示されます
    
    Aこちらは正しく動きません
    ・Button1を実行
    ・Button2を実行(データベースにデータが存在しない場合、ListBo2にデータは何も表示されない)
    ・Button1を実行
    ・ListBox2に追加でデータが表示されない。ただし、実際にはdataTable2にデータは格納されている。
    
    using System;
    using System.Data;
    using System.Windows.Forms;
    using System.Data.SqlClient;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            //----------------------------
            // dataTable1の構造とDataTable2の構造は違います。
    
    
            public Form1()
            {
                InitializeComponent();
            }
    
            //普通のDataTable
            DataTable dataTable1 = new DataTable();
            //型付データセット
            DataTable dataTable2 = new DataSet().Table;
    
            //Formロード
            private void Form1_Load(object sender, EventArgs e)
            {
                //リストボックスに表示
                var strSql = @"SELECT * FROM T where col1 = 'X'";
                dataTable1 = DoSomething.selectSQL(strSql);
                listBox1.DataSource = dataTable1;
                listBox1.DisplayMember = "column1";
    
                listBox2.DataSource = dataTable2;
                listBox2.DisplayMember = "column1";
            }
    
            //選択されたListBox1の値をListBox2に表示させる
            private void button1_Click_1(object sender, EventArgs e)
            {
                var row = listBox1.SelectedItem as DataRowView;
                dataTable2.Rows.Add(row["column1"].ToString());
            }
    
            //ListBox2に新しくデータをセットする
            private void button2_Click_1(object sender, EventArgs e)
            {
                var strSql = @"SELECT * FROM T where col1 = 'Y'";
                dataTable2.Clear();
                dataTable2 = DoSomething.selectSQL(strSql);
                listBox2.DataSource = dataTable2;
                listBox2.DisplayMember = "column1";
            }
        }
    
            class DoSomething  //こちらはClassファイルとして別で本当は持っています
            {
                public static DataTable selectSQL(string sql)
                {
                    DataTable dt = new DataTable();
    
                    using (var con = new SqlConnection("Data Source = datasource"))
                    {
                        con.Open();
                        using (SqlCommand command = new SqlCommand(sql, con))
                        {
                            using (SqlDataAdapter adapter = new SqlDataAdapter())
                            {
                  //実行時にDBにデータが無いとButton2を押してもデータがListBox2に表示されない
                                adapter.SelectCommand = command;
                                adapter.Fill(dt);
                                return dt;
                            }
                        }
                    }
                }
            }
    }

違反を報告
[ 親 34184 / □ Tree ] 返信 削除キー/

▲[ 34189 ] / ▼[ 34192 ]
■34190 / 5階層)  Re[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 で受けるしかなかったのでしょうけれども、
    今回提示した形で修正すれば、型付の方で扱えるようになると思います。
違反を報告
[ 親 34184 / □ Tree ] 返信 削除キー/

▲[ 34190 ] / 返信無し
■34192 / 6階層)  Re[6]: ListBoxにデータが表示されない
□投稿者/ ケミカル 一般人(4回)-(2019/03/11(Mon) 18:21:56)
  • アイコン>var newTbl = DoSomething.selectSQL(strSql);
    >dataTable2.Merge(dataTable2, true);

    dataTable2.Merge(newTbl, true);で解決する事ができました。

    色々と勘違いしていた部分があり勉強になりました。ありがとうございます。
解決み!
違反を報告
[ 親 34184 / □ Tree ] 返信 削除キー/


Mode/  Pass/


- Child Tree -