C# ListView 自作列幅調整 描画されない

このQ&Aのポイント
  • C#のListViewでリストビューの列幅を自作し、描画更新されない状態になる問題について質問です。
  • ListViewに3列追加し幅が変更された際、2列目の幅のみを引き延ばす操作を行うと、描画更新されない状態になります。
  • サンプルコードと画像が提示されていますが、操作手順によってListViewの描画が正常に表示されない問題が発生しています。
回答を見る
  • ベストアンサー

C# ListView 自作列幅調整 描画されない

いつもお世話になっております。 今回はC#のListViewで皆様にお聞きしたいことがあり、 質問させて頂きました。 ListViewに3列追加しListViewの幅が変更された際に 2列目のみを引き延ばすものを作りたいと思っています。 しかし、以下操作を行うと、ListViewのリサイズ等で 描画更新されない状態になってしまいます。 (また、リストアイテムをクリックするとその列は描画されるのですが、 アイテムの描画開始Y位置がおかしくなっています。)  1.縦スクロールバーが表示されるまで縮小する  2.スクロールバーのノブを下に移動  3.縦スクロールバーの表示が消えるまで拡大する サンプルコード及び画像を添付いたします。 内容は、  3列のListViewに適当なアイテムを10個追加し、  OnClientSizeChangedでClientSize.Widthと1列3列の幅から  2列目の幅を算出・設定しています。 ※画像は、以下コントロールをFormに張り付けただけのもので  問題の起こる操作をした際のものになります。 class MyListView : ListView {   public const int COL_1_WIDTH  = 30;   public const int COL_3_WIDTH  = 75;   enum LISTVIEW_COL   {     COL1,     COL2,     COL3,     NUM   }   public MyListView() {     Dock = DockStyle.Fill;     HeaderStyle = ColumnHeaderStyle.None;     FullRowSelect = true;     HideSelection = false;     View = System.Windows.Forms.View.Details;     //ヘッダ追加     ColumnHeader column1 = new ColumnHeader();     ColumnHeader column2 = new ColumnHeader();     ColumnHeader column3 = new ColumnHeader();     ColumnHeader[] columnHeaders = { column1, column2, column3 };     this.Columns.AddRange( columnHeaders );     //ヘッダ幅追加     this.Columns[( int )LISTVIEW_COL.COL1].Width = COL_1_WIDTH;  //1列固定     this.Columns[( int )LISTVIEW_COL.COL3].Width = COL_3_WIDTH; //3列固定     int width = ClientRectangle.Width;     for( int i = 0; i < Columns.Count; i++ ) {       if( i == ( int )LISTVIEW_COL.COL2 ) { continue; }       width -= Columns[i].Width;     }     //2列 リストビューの幅いっぱいになるように調節     this.Columns[( int )LISTVIEW_COL.COL2].Width = width;     //適当にアイテム追加     for( int i = 0; i < 10; i++ ) {       string[] strs = { "COL1", "COL2", "COL3" };       ListViewItem item = new ListViewItem( strs );       this.Items.Add( item );     }   }   protected override void OnClientSizeChanged( EventArgs e ) {     base.OnClientSizeChanged( e );     //2列の幅を調整     int width = ClientRectangle.Width;     for( int i = 0; i < Columns.Count; i++ ) {       if( i == ( int )LISTVIEW_COL.COL2 ) { continue; }       width -= Columns[i].Width;     }     Columns[( int )LISTVIEW_COL.COL2].Width = width;   } } 何故このようになってしまうのかご存知の方いらっしゃいましたら教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
noname#212058
noname#212058
回答No.1

ListView の列幅を内部で変更したことによって、コントロールの再描画領域の判定に狂いが生じているのでしょう。列幅を変更した後で、自分で強制的に再描画をするようにするのが最も簡便です。 具体的には、OnClientSizeChanged の最後で this.Refresh(); を実行するようにしましょう。(コントロール内のデータ量があまりにも多い場合などで「チラつき」が発生する可能性があります。その場合は、列幅の変更方法自体を再検討したほうが良いです)

okwaveid_1
質問者

お礼

ご回答ありがとうございます。 > ListView の列幅を内部で変更したことによって、コントロールの再描画領域の判定に狂いが生じているのでしょう。 なるほど、確かにクリックした時のリストアイテムのBounds値がおかしな値になっていました。(何故かクリックした時はその行のリストアイテムは描画されました。) > 具体的には、OnClientSizeChanged の最後で this.Refresh(); を実行するようにしましょう。(コントロール内のデータ量があまりにも多い場合などで「チラつき」が発生する可能性があります。その場合は、列幅の変更方法自体を再検討したほうが良いです) 私の環境で表示されるようになりました!ありがとうございます。 (ただ、ちらつきがひどいですが...) 糸口が見えましたので、変更方法を見直してみます! ありがとうございました!

関連するQ&A

  • ListViewとArrayListの連動がうまくいきません

    メールソフトの中で既読、未読を設定するフラグを実装しているのですが ListViewのカラムクリック時の昇順・降順設定を追加するとなぜか おかしな表示になってしまいます。 未読(フラグがtrue)の時は太字で表示されて、既読(フラグがfalse)の 場合は通常のフォントで表示するようにしてあるのですが、 指定している配列ですべてtrueにしているのにもかかわらず表示されるのは trueとfalseの結果の表示がまばらに出てしまって何が原因なのかが 分かりません。 どうすればこれを解決する事が出来るでしょうか? 環境はVS2005(C#)、.NET Framework 2.0です。 リストビューの昇順・降順ロジックはどぼんの.NET Tipsに 載っている文字列、数字、日付で比較が可能なタイプのを 使用しています。 public void UpdateListView() { ArrayList list = null; int i = 0; if (listView1.Columns[1].Text == "差出人") { // 受信メールの場合 list = collectionMail[RECEIVE]; } else if (listView1.Columns[1].Text == "差出人または宛先") { // 削除メールの場合 list = collectionMail[DELETE]; } listView1.BeginUpdate(); // リストビューの内容をクリアする listView1.Items.Clear(); // ListViewを設定する foreach (Mail mail in list) { ListViewItem item = new ListViewItem(mail.subject); item.SubItems.Add(mail.address); item.SubItems.Add(mail.date); // この2行を追加 item.Tag = i; i++; listView1.Items.Add(item); // 未読(未送信)の場合は、フォントを太字にする int index = listView1.Items.Count - 1; if (mail.notReadYet == true) { listView1.Items[index].Font = new Font(this.Font, FontStyle.Bold); } } listView1.EndUpdate(); } private void listView1_DoubleClick(object sender, EventArgs e) { Mail mail = null; ListViewItem item = listView1.SelectedItems[0]; if (listView1.Columns[1].Text == "差出人") { mail = (Mail)collectionMail[RECEIVE][(int)item.Tag]; } else if (listView1.Columns[1].Text == "差出人または宛先") { mail = (Mail)collectionMail[DELETE][(int)item.Tag]; } mail.notReadYet = false; textBox1.Text = mail.body; UpdateListView(); } private void Form1_Load(object sender, EventArgs e) { // ListViewにアイテムを追加する for (int no = 0; no < subject.Length; no++) { Mail mail = new Mail(subject[no], address[no], date[no], body[no], read[no]); collectionMail[RECEIVE].Add(mail); } UpdateTreeView(); UpdateListView(); // ListViewItemComparerの作成と設定 listViewItemSorter = new ListViewItemComparer(); listViewItemSorter.ColumnModes = new ListViewItemComparer.ComparerMode[] { ListViewItemComparer.ComparerMode.String, ListViewItemComparer.ComparerMode.String, ListViewItemComparer.ComparerMode.DateTime }; // ListViewItemSorterを指定する listView1.ListViewItemSorter = listViewItemSorter; }

  • ストアアプリ開発 C# ListViewについて

    ストアアプリ開発 C#初心者です。 サーバーからデータ取得後、 ListViewにデータを追加したいのですがよくわかりません。 ListViewに表示させたいのは日付、タイトル、画像です。 xaml↓ <ListView Grid.Row="1" x:Name="ListView1"></ListView> C# foreach (var item in blog_list){ ListViewItem addItem = new ListViewItem(); addItem.Tag = item.GetObject().GetNamedString("id"); addItem.Content = item.GetObject().GetNamedString("name"); ListView1.Items.Add(addItem); } 本当に初心者で申し訳ないのですがわかりやすい 解説等してるサイトありましたら教えてください。

  • ArrayListのソートについて

    プログラム上でListViewのカラムをクリックするとソートされる プログラムを作ろうと入れたのですが、リストはソートされるのに 中身(ArrayList)がソートされていないためソート後のアイテムを クリックしても違う値しか出てきません。 それにはArrayListのソートが必要と言う事が書いてあったので 実装をしてみたのですが、比較ができないようなエラーが出て うまくソートもできませんでした。 どうすればListViewのカラムソートと連動してArrayListのソートが 出来るようになるでしょうか? 開発環境はVS2005(C#) .NET2.0です。 サンプルクラスは以下の通りです。 public void UpdateListView() { ArrayList list = null; if (listView1.Columns[1].Text == "差出人") { // 受信メールの場合 list = collectionMail[RECEIVE]; } else if (listView1.Columns[1].Text == "差出人または宛先") { // 削除メールの場合 list = collectionMail[DELETE]; } listView1.BeginUpdate(); // リストビューの内容をクリアする listView1.Items.Clear(); // ListViewを設定する foreach (Mail mail in list) { ListViewItem item = new ListViewItem(mail.subject); item.SubItems.Add(mail.address); listView1.Items.Add(item); } listView1.EndUpdate(); } private void Form1_Load(object sender, EventArgs e) { // ListViewにアイテムを追加する for (int no = 0; no < subject.Length; no++) { Mail mail = new Mail(subject[no], address[no], body[no]); collectionMail[RECEIVE].Add(mail); } UpdateTreeView(); UpdateListView(); } public class Mail { public string subject; public string address; public string body; public Mail(string subject, string address, string body) { this.subject = subject; this.address = address; this.body = body; } }

  • C# リストビューの値を取得

    foreach (ListViewItem item in ListView1.SelectedItems) { MessageBox.Show(item.Text); } 上記の書き方だと1カラム目しか取得できないのですが、これを2カラム目3カラム目と順番に表示するにはどうしたらよいでしょうか?

  • C# ListView内の検索機能について

    C#にて次のようなアプリを作成しています。 まず、MainであるForm1に、ListViewと<追加>ボタンがあります。そのボタンを押下すると入力Form(Form2)が表示されます。Form2ではListViewに追加したい項目を入力し、Form2内の<リスト追加>ボタンを押下のタイミングでForm1のListViewにその項目が追加されていきます。 MainのForm1には<検索>ボタンと検索キーワード入力テキストが用意されていて、ボタン押下のタイミングでForm1内のListViewの項目と照らし合わせ、同じ項目があれば、その項目をForm3のListViewに追加/表示させようと考えています。 この"検索"の機能が実装できません。 string keyWord = textBox1.Text; ListViewItem foundItem = listView1.FindItemWithText(keyWord, true, 0, true); if (foundItem != null) { fm3 = new Form3(); fm3.listView1.TopItem = foundItem; } fm3.Show(); 上記のように考えていますが、うまくいきません。 エラーはありません。 どうにか検索機能を実装させるために、どうか皆さんアドバイスのほど、よろしくお願いいたします。

  • DataGridの列幅を実行時に変更したい

    Web画面のSpreadからDataGridへ変更する対応を行っていて、 Spreadの列幅と同じ値を以下のようにテンプレート列を使用して、 ボタンやらチェックボックスやらラベルやら配置をして設定しました。 (TemplateColumnのWidthを使用するとSpreadと同じ値をいれても1/4くらいになってしまったので。) <Columns>  <asp:TemplateColumn>   <ItemTemplate>    <asp:Button id="grdButton" runat="server" Width="45"></asp:Button>   </ItemTemplate>  </asp:TemplateColumn>  <asp:TemplateColumn>   <ItemTemplate>    <asp:Button id="grdButton1" runat="server" Width="45"></asp:Button>   </ItemTemplate>  </asp:TemplateColumn> :          : しかし、実行時に条件によって見える列が変化するため 列を非表示にしたいのですが、Visibled = Falseにしてしまうと、 JavaScriptで、隠している列の値がとれないので、Width = 0にしたいのですが、 grd.Columns(col_2).HeaderStyle.Width = New Unit(0) grd.Columns(col_2).ItemStyle.Width = New Unit(0) というように記述しても列幅が0になっていません。 上記のように実現したければ、どのような手段があるでしょうか?

  • listviewの画面遷移について

    初心者です。 現在カスタムlistviewにて各行に画像とテキストを表示させており、各行をクリックした時に別のActivityに移行させたいのですが、下記ソースにてクリックしても何も動作がしない状態です。 どうかご指南をお願い致します。 public class CustomListViewActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Bitmap image; image = BitmapFactory.decodeResource(getResources(), R.drawable.tb); Bitmap image2; image2 = BitmapFactory.decodeResource(getResources(), R.drawable.tb2); Bitmap image3; image3 = BitmapFactory.decodeResource(getResources(), R.drawable.tb3); List<CustomData> objects = new ArrayList<CustomData>(); CustomData item1 = new CustomData(); item1.setImagaData(image); item1.setTextData("1行目のテキスト"); CustomData item2 = new CustomData(); item2.setImagaData(image2); item2.setTextData("2行目のテキスト"); CustomData item3 = new CustomData(); item3.setImagaData(image3); item3.setTextData("3行目のテキスト"); objects.add(item1); objects.add(item2); objects.add(item3); CustomAdapter customAdapater = new CustomAdapter(this, 0, objects); ListView listView = (ListView)findViewById(R.id.list); listView.setAdapter(customAdapater); } protected void onListItemClick(ListView l, View v, int position, long id) { switch (position) { case 0: startActivity(new Intent(this, Item1Activity.class)); break; case 1: startActivity(new Intent(this, Item2Activity.class)); break; case 2: startActivity(new Intent(this, Item3Activity.class)); break; } } }

  • コンボボックスのマウスホイールを無効にしたい

    DataGridView内にコンボボックスを設定しております。 マウスのホイールボタンは、DataGridViewの縦スクロールに 使いたいのですが、DataGridView内のコンボボックスに カーソルがある場合、コンボボックス内のデータが変わってしまいます。 ユーザー側と打ち合わせた結果、コンボボックスにカーソルが ある時に、マウスのホイールボタンを無効に出来ないかと 言われております。 色々調べてみましたが、私では分からず、教えて下さい。 (サンプルソース) Dim column1 As New DataGridViewComboBoxColumn() With DataGridView1 .Columns.Clear() .Columns.Add("Col01", "列1") With column1 .Items.AddRange(New String() {"Item01", "Item02", "Item03"}) .Name = "Col02" .HeaderText = "列2" End With .Columns.Add(column1) For i As Integer = 0 To 100 .Rows.Add() Next i End With

  • アプレットを再描画させたい

    アプレットを作りましたが、ウィンドウの大きさを変えた時にも描いたオブジェクトをrepaintを使って再描画させるのは どのようにすればよいのでしょうか。 _______________________________ public class QQ_Oekaki extends Applet implements ActionListener { Graphics g; Color col; int w; int h; Button btnBlue; Button btnYellow; public void init() { g = getGraphics(); btnBlue = new Button("Blue"); this.add(btnBlue); btnBlue.addActionListener(this); btnBlue.setFont(new Font("SansSerif", Font.ITALIC, 10)); btnBlue.setForeground(Color.blue); btnYellow = new Button("Yellow"); this.add(btnYellow); btnYellow.addActionListener(this); btnYellow.setFont(new Font("SansSerif", Font.ITALIC, 10)); btnYellow.setForeground(Color.yellow); this.addMouseMotionListener ( new MouseMotionAdapter() { public void mouseDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); g.setColor(Color.green); g.setColor(col); g.fillRect(x,y,5,5); } } ); } public void actionPerformed(ActionEvent ae) { if (ae.getActionCommand()=="Yellow") { col = Color.yellow; } if (ae.getActionCommand()=="Blue") { col = Color.BLUE; } } }

  • androidアプリのlistviewについて質問

    現在Listviewにてテキストと画像を表示させています。 各行をクリックした時に、それぞれ別のActivityに移行させたいのですが、 初心者の為、悪戦苦闘しています。 わかる方がいましたら、アドバイスをお願い致します。 現在のソースは以下のとおりで、各行をタッチしても何も起こらない状況です。 public class CustomListViewActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Bitmap image; image = BitmapFactory.decodeResource(getResources(), R.drawable.tb); Bitmap image2; image2 = BitmapFactory.decodeResource(getResources(), R.drawable.tb2); Bitmap image3; image3 = BitmapFactory.decodeResource(getResources(), R.drawable.tb3); List<CustomData> objects = new ArrayList<CustomData>(); CustomData item1 = new CustomData(); item1.setImagaData(image); item1.setTextData("1行目のテキスト"); CustomData item2 = new CustomData(); item2.setImagaData(image2); item2.setTextData("2行目のテキスト"); CustomData item3 = new CustomData(); item3.setImagaData(image3); item3.setTextData("3行目のテキスト"); objects.add(item1); objects.add(item2); objects.add(item3); CustomAdapter customAdapater = new CustomAdapter(this, 0, objects); ListView listView = (ListView)findViewById(R.id.list); listView.setAdapter(customAdapater); } protected void onListItemClick(ListView l, View v, int position, long id) { switch (position) { case 0: startActivity(new Intent(this, ItemDetailActivity.class)); break; case 1: startActivity(new Intent(this, ItemDetailActivity.class)); break; case 2: startActivity(new Intent(this, ItemDetailActivity.class)); break; } } }

専門家に質問してみよう