DOBON.NETプログラミング道掲示板
(現在 過去ログ2 を表示中)

[ 最新記事及び返信フォームをトピックトップへ ]

■33554 / inTopicNo.1)  ListViewのページは指定できるのでしょうか?(ASP.NETではありません)
  
□投稿者/ もんちきTwinTurbo 一般人(3回)-(2017/01/12(Thu) 16:04:35)
  • アイコン環境/言語:[OS : Windows 7 / 言語 : C#] 
    分類:[.NET] 

    【解決したい問題】

    お世話になります。昨日イベントハンドラの追加について質問した者です。
    大変勉強になりました。ありがとうございました。

    引き続き、コントロールの動的な追加について勉強しているのですが、
    またしても問題に突き当たってしまいました。

    現在フォームにタブコントロール1を配置し、動的にタブページを追加、
    更に各ページにリストビューを配置しようとしています。

    作成したのは以下のコードです。

    private void Form1_Load(object sender, EventArgs e)
    {
    for (int i = 0; i < 5; i++)
    {
    TabPage myTabPage = new TabPage(i.ToString());
    tabControl1.TabPages.Add(myTabPage);
    this.listviews = new System.Windows.Forms.ListView();
    this.listviews.Name = myTabPage.Text;

    ColumnHeader Itm1, Itm2, Itm3;
    ch1 = new ColumnHeader();
    ch1.Text = "Item1";
    ch1.Width = 50;

    ColumnHeader[] colHeaderRegValue = { Itm1, Itm2, Itm3 };
    this.listviews.Columns.AddRange(colHeaderRegValue);
    myTabPage.Controls.Add(this.listviews);
    this.listviews.DoubleClick += new EventHandler(listviews_DoubleClick);
    string[] rowdata = { "AAA", "BBB", "CCC" };
    this.listviews.Items.Add(new ListViewItem(rowdata));
    }
    }

    この場合、当然ですがforループで配置した全てのタブページに、
    リストビューと同じアイテムが追加されます。

    問題は、リストビューにページインデックスの様なプロパティがないため、
    ページの指定の仕方が分からないことです。

    例えばリストビューのダブルクリックのイベントの中で

    void listviews_DoubleClick(object sender, EventArgs e)
    {
    MessageBox.Show(tabControl1.SelectedTab.Text);
    }

    この様に選択されているタブ名を取得すれば、どこのページが開かれているかは
    確認できますが、例えばタブコントロールの任意のページを指定してアイテムを
    追加したい場合、どの様にすれば良いのでしょうか?

    どこのタブコントロールのページを開いていても、最後にアイテムを追加した
    リストビューの下にアイテムが追加されていきます。

    何度も済みません。よろしくお願いします。
引用返信 削除キー/
■33555 / inTopicNo.2)  Re[1]: ListViewのページは指定できるのでしょうか?(ASP.NETではありません)
□投稿者/ 魔界の仮面弁士 大御所(1061回)-(2017/01/12(Thu) 17:02:32)
  • アイコンNo33554に返信(もんちきTwinTurboさんの記事)
    > どこのタブコントロールのページを開いていても、最後にアイテムを追加した
    > リストビューの下にアイテムが追加されていきます。

    this.listviews は配列でもコレクションでも無いので、
    同時に保持できる ListView は一つだけです。

    しかも、ループのたびに listviews 変数の参照先を書き換えているので、
    結果として、最後の ListView のみが保持された状態になります。


    現在の処理の流れは、下記のような流れになっているわけですが、
    下記のコードでイメージが掴めるでしょうか。

    for (int i = 0; i < 5; i++)
    {
     TabPage myTabPage = TabPage生成処理(i); // i ページ目を作成
     ListView lv = ListView生成処理(myTabPage); // そのページにListViewを追加
     this.listviews = lv; // 変数の参照先を、今追加したListViewへの参照に置き換え
    }



    > void listviews_DoubleClick(object sender, EventArgs e)
    > {
    >  MessageBox.Show(tabControl1.SelectedTab.Text);
    > }

    イベントの発生元は sender に入っていますから、
      ListView lv = (ListView)sender;
    のようにすれば、this.listviews の出番は無いと思います。



    > 問題は、リストビューにページインデックスの様なプロパティがないため、
    > ページの指定の仕方が分からないことです。

    複数のデータを保持しておき、それを再利用するためには、
    「コレクション」や「配列」が使われます。



    たとえば、TabPage は TabControl によって管理されていますよね。

    tabControl1.TabPages.Add( 新しいページ ); の処理で使った
    TabPages プロパティは、TabPage 用のコレクション型になっています。


    同様に、myTabPage.Controls.Add(lv); の処理で使った
    Controls プロパティは、Control 用のコレクションになっています。

    tabControl1.TabPages[p] とすれば pページ目の TabPage が得られます。

    現在選択中のタブページなら、tabControl1.SelectedTab で得られますが、これは
    tabControl1.TabPages[tabControl1.SelectedIndex] と同義です。


    こうして得られた TabPage に対して、.Controls[0] とすれば、そのページ上に
    0 番目に追加されたコントロール(この場合は恐らく ListView)を
    得ることができます。



    ただ、上記の方法では回りくどいので、こういう場合には、
    管理用のコレクションを自分で用意しておくのが良いでしょう。


    たとえば、フィールド変数をコレクションに変更し、

     // private ListView listviews;
     private List<ListView> listviews = new List<ListView>();

    そのうえで、Load 時のループ処理を

      ListView lv = new ListView();
      lv.Name = myTabPage.Text;
      //
      // 略
      //
      lv.Columns.AddRange(colHeaderRegValue);
      myTabPage.Controls.Add(lv);
      lv.DoubleClick += new EventHandler(listviews_DoubleClick);
      string[] rowdata = { "AAA", "BBB", "CCC" };
      lv.Items.Add(new ListViewItem(rowdata));

      // ★コレクションに追加
      this.listviews.Add(lv);

    のようにしてやれば、this.listviews[ページ番号] のようにして利用できます。
引用返信 削除キー/
■33556 / inTopicNo.3)  Re[2]: ListViewのページは指定できるのでしょうか?(ASP.NETではありません)
□投稿者/ もんちきTwinTurbo 一般人(4回)-(2017/01/13(Fri) 00:11:49)
  • アイコン魔界の仮面弁士様、ご教授ありがとうございます。

    > しかも、ループのたびに listviews 変数の参照先を書き換えているので、
    > 結果として、最後の ListView のみが保持された状態になります。

    そういうことだったのですね。

    自分で確認するため

    this.listviews.Name = i.ToString();

    に変更してみたところ、確かにリストビュー全てのページが同じ名前でした;

    > ただ、上記の方法では回りくどいので、こういう場合には、
    > 管理用のコレクションを自分で用意しておくのが良いでしょう。

    しかも、より実用的な代替例までお示しいただき、感謝いたします。
    こちらも早速試してみましたが、期待通りの結果が得られました。

    ご丁寧に、しかも非常に分かりやすく説明していただいたおかげで、
    非常に良く分かりました。

    とても勉強になりました。ありがとうございました。
解決み!
引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

Mode/  Pass/


- Child Tree -