C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: C# ListView 列幅調整 描画されない


(過去ログ 128 を表示中)

[トピック内 3 記事 (1 - 3 表示)]  << 0 >>

■76219 / inTopicNo.1)  C# ListView 列幅調整 描画されない
  
□投稿者/ 人生の初心者 (1回)-(2015/06/12(Fri) 11:18:49)

分類:[.NET 全般] 

C#のListViewで皆様にお聞きしたいことがあり質問させて頂きました。

開発環境は、
Visual Studio 2012
.NET Framework 4.5
です。

ListViewに3列追加しListViewの幅が変更された際に
2列目のみを引き延ばすものを作りました。

処理内容は、OnClientSizeChangedでClientSize.Widthと1列3列の固定幅から
2列目の幅を算出し設定するというものです。

リスト幅の動きは概ね理想通りだったのですが、
以下操作を行うとListViewのリサイズ等で描画更新されない状態になってしまう事が分かりました。
(また、リストアイテムをクリックするとその列は描画されるのですがアイテムの描画開始Y位置がおかしくなっています。)
 1.縦スクロールバーが表示されるまで縮小する
 2.スクロールバーのノブを下に移動
 3.縦スクロールバーの表示が消えるまで拡大する

ListViewのコードを以下に記述いたします。
※実際に使用しているコードから問題発生部分を抜き取ったものになります。
 実戦で使用しているコードでは、OwnerDrawをtrueにしており、OnDrawSubItem()で描画をしています。
 問題発生手順を行うと、リサイズ時にOnDrawSubItem()に処理が来なくなるため、再描画されていないと判断して先ほど記述しました。
 また、アイテムの描画開始Y位置がおかしいというのは、クリックしたときのOnDrawSubItem()でイベントデータの1列目item.BoundsがY=16で来るように
 なってしまう事が分かったため、先ほど記述しました。
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;
  }
}

何故このような現象が起きてしまうのか、どうしてもよくわからないため、
お詳しい方、ご教示ください。
また、お作法的にこんな処理をしてはいけない、こうするべき等のご指摘を頂けると幸いです。

引用返信 編集キー/
■76220 / inTopicNo.2)  Re[1]: C# ListView 列幅調整 描画されない
□投稿者/ Hongliang (319回)-(2015/06/12(Fri) 12:01:31)
何かWindows/WinForm内部で処理がバッティングしたんでしょうね。
困ったときのBeginInvoke。

protected override void OnClientSizeChanged( EventArgs e ) {
	base.OnClientSizeChanged( e );
	if (this.IsHandleCreated) {
		this.BeginInvoke(new MethodInvoker(this.AdjustColumnSize));
	}
	else {
		this.AdjustColumnSize();
	}
}
private void AdjustColumnSize() {
	//2列の幅を調整
	//略
}

引用返信 編集キー/
■76226 / inTopicNo.3)  Re[2]: C# ListView 列幅調整 描画されない
□投稿者/ 人生の初心者 (2回)-(2015/06/12(Fri) 17:03:26)
No76220 (Hongliang さん) に返信
> 何かWindows/WinForm内部で処理がバッティングしたんでしょうね。
> 困ったときのBeginInvoke。
>
> protected override void OnClientSizeChanged( EventArgs e ) {
> base.OnClientSizeChanged( e );
> if (this.IsHandleCreated) {
> this.BeginInvoke(new MethodInvoker(this.AdjustColumnSize));
> }
> else {
> this.AdjustColumnSize();
> }
> }
> private void AdjustColumnSize() {
> //2列の幅を調整
> //略
> }
>

早速のご回答ありがとうございます。
返信が遅くなり申し訳ございません。
(ちゃんと理解してからお返事を書こうと思いましたが、時間ばかりが過ぎてしまい...)

上記処理に置き換えたところ、正常に動作出来ました。

BeginInvoke, IsHandleCreated についてまだ完全な理解が出来ておりませんので、勉強しておきます。
助かりました、ありがとうございました。
解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -