web-dev-qa-db-ja.com

列のコンテンツとヘッダーの両方に基づくListView AutoResizeColumns

この2つの方法を使用して、列の内容とヘッダーの応答に基づいて列の長さを調整します。

ListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); ListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);

しかし、両方に基づいて調整する方法は?つまり、ヘッダーと列のコンテンツが最長になるように調整します。

20
william007

lvw.Columns[0].Width = -2

詳細については、MSDNの備考を参照してください: http://msdn.Microsoft.com/en-us/library/system.windows.forms.columnheader.width.aspx

また、MSDNは「列見出しの幅に自動調整するには、Widthプロパティを-2に設定する」と述べていますが、実際には、列見出しと列のコンテンツに対して機能します。

これを証明するコードは次のとおりです。

    lvw.Columns.Add(new String('x', 25));   // short header
    lvw.Items.Add(new String('x', 100));    // long content

    lvw.Columns[0].Width = -2;
    // in result column width will be set to fit content
28
Anton Kedrov

答えは here で、両方のサイズ変更オプションを呼び出すとうまくいきます:

myListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
myListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
18
Tanguy

これは、コンテンツとヘッダーの両方の列幅を調整するために使用するものです。

public static void autoResizeColumns(ListView lv)
{
    lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
    ListView.ColumnHeaderCollection cc = lv.Columns;
    for (int i = 0; i < cc.Count; i++)
    {
        int colWidth = TextRenderer.MeasureText(cc[i].Text, lv.Font).Width + 10;
        if (colWidth > cc[i].Width)
        {
            cc[i].Width = colWidth;
        }
    }
}

使用例:

autoResizeColumns(listView1);

メソッドは十分にテストされていませんが、少なくとも私が使用しているコンテキストでは機能します。

4
matsolof

実際に、MeasureTextを使用して、残りのスペースを計算し、何らかの方法ですべての列に配分することが可能です。しかし、これは私がすばやくコーディングした迅速で汚いアプローチです:

    /// <summary>
    /// Enables autoresizing for specific listview.
    /// You can specify how much to scale in columnScaleNumbers array - length of that array
    /// should match column count which you have.
    /// </summary>
    /// <param name="listView">control for which to enable auto-resize</param>
    /// <param name="columnScaleNumbers">Percentage or numbers how much each column will be scaled.</param>
    private void EnableAutoresize(ListView listView, params int[] columnScaleNumbers)
    {
        listView.View = View.Details;
        for( int i = 0; i < columnScaleNumbers.Length; i++ )
        {
            if( i >= listView.Columns.Count )
                break;
            listView.Columns[i].Tag = columnScaleNumbers[i];
        }

        listView.SizeChanged += lvw_SizeChanged;
        DoResize(listView);
    }

    void lvw_SizeChanged(object sender, EventArgs e)
    {
        ListView listView = sender as ListView;
        DoResize(listView);
    }

    bool Resizing = false;
    void DoResize( ListView listView )
    {
        // Don't allow overlapping of SizeChanged calls
        if (!Resizing)
        {
            // Set the resizing flag
            Resizing = true;

            if (listView != null)
            {
                float totalColumnWidth = 0;

                // Get the sum of all column tags
                for (int i = 0; i < listView.Columns.Count; i++)
                    totalColumnWidth += Convert.ToInt32(listView.Columns[i].Tag);

                // Calculate the percentage of space each column should 
                // occupy in reference to the other columns and then set the 
                // width of the column to that percentage of the visible space.
                for (int i = 0; i < listView.Columns.Count; i++)
                {
                    float colPercentage = (Convert.ToInt32(listView.Columns[i].Tag) / totalColumnWidth);
                    listView.Columns[i].Width = (int)(colPercentage * listView.ClientRectangle.Width);
                }
            }
        }

        // Clear the resizing flag
        Resizing = false;            
    }

そして、あなたが持っている列の数に応じて-各列の「パーセント」または単に数値を指定します。たとえば3列の場合-呼び出しは次のようになります。

        EnableAutoresize(listView1, 6, 3, 1);

これにより、列サイズが次のように分散されます。6* 100%/(6 + 3 + 1)=最初の列は60%、次の列は30%、残りの列は10%。

これはどういうわけか貧乏人クイック実装です。 :-)

1
TarmoPikaro

以下は、任意のリストビューに使用できるC#ソリューションです。列数とヘッダーは、特定のリストビューで変更されないと想定しています。ヘッダーの幅を毎回再計算する場合は(ヘッダーが変更された場合、または列数が変更された場合)、listViewHeaderWidths辞書を削除します。

    private Dictionary<string, int[]> listViewHeaderWidths = new Dictionary<string, int[]>();    
    private void ResizeListViewColumns(ListView lv)
    {
        int[] headerWidths = listViewHeaderWidths.ContainsKey(lv.Name) ? listViewHeaderWidths[lv.Name] : null;

        lv.BeginUpdate();

        if (headerWidths == null)
        {
            lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);

            headerWidths = new int[lv.Columns.Count];

            for (int i = 0; i < lv.Columns.Count; i++)
            {
                headerWidths[i] = lv.Columns[i].Width;
            }

            listViewHeaderWidths.Add(lv.Name, headerWidths);
        }

        lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);

        for(int j = 0; j < lv.Columns.Count; j++)
        {
            lv.Columns[j].Width = Math.Max(lv.Columns[j].Width, headerWidths[j]);
        }

        lv.EndUpdate();
    }
0
GreggD

私の場合、次の手順でこれを行います(2列のデータの場合)。

  1. 列ごとにColumnHeaderオブジェクトを作成します。
  2. (両方の列の)HeaderSizeに基づくAutoResizeによるサイズの設定
  3. その値を整数変数に格納します
  4. ColumnContent(両方の列)に基づいてAutoResizeでサイズを設定する
  5. (各列の)古い値と新しい値の間の最大基準を使用して、各整数変数の値を更新します。
  6. 各ColumnHeaderオブジェクトの列幅サイズを設定します。

VB.NETの場合:

'Create two header objects as ColumnHeader Class
Dim header1, header2 As ColumnHeader

'Construcción de los objetos header
header1 = New ColumnHeader
header1.Text = "ID"
header1.TextAlign = HorizontalAlignment.Right
header1.Width = 10

header2 = New ColumnHeader
header2.Text = "Combinaciones a Procesar"
header2.TextAlign = HorizontalAlignment.Left
header2.Width = 10

'Add two columns using your news headers objects 
ListView.Columns.Add(header1)
ListView.Columns.Add(header2)

'Fill three rows of data, for each column
ListView.Items.Add(New ListViewItem({"A1", "B1"}))
ListView.Items.Add(New ListViewItem({"A2", "B2"}))
ListView.Items.Add(New ListViewItem({"A3", "B3"}))

'Change the size of each column
Dim headsz1, headsz2 As Integer
SelectionInTable.ListView.AutoResizeColumn(0,             ColumnHeaderAutoResizeStyle.HeaderSize)
SelectionInTable.ListView.AutoResizeColumn(1, ColumnHeaderAutoResizeStyle.HeaderSize)
headsz1 = header1.Width
headsz2 = header2.Width
SelectionInTable.ListView.AutoResizeColumn(0, ColumnHeaderAutoResizeStyle.ColumnContent)
SelectionInTable.ListView.AutoResizeColumn(1,     ColumnHeaderAutoResizeStyle.ColumnContent)
headsz1 = Math.Max(headsz1, header1.Width)
headsz2 = Math.Max(headsz2, header2.Width)
header1.Width = headsz1
header2.Width = headsz2
0
Asrhael

これは簡単です(理解するのに少し時間がかかりましたが)...

すべてのヘッダーテキストが表示されるように、幅は少なくとも列ヘッダーと同じ大きさでなければならないことがわかっています。それを超えて、幅はコンテンツを収容するためにより大きく拡大することができます。したがって、次のことを行います。

  1. 列をヘッダーに合わせて自動サイズ調整します。
  2. 列を反復処理し、各列の最小幅プロパティを現在の列幅に設定します(これにより、列が小さすぎてヘッダーが表示されないことが保証されます)。
  3. 今後は、コンテンツごとに列のサイズを自動調整します。

他のポスターが示唆するように、幅を個別に追跡してリセットする必要はありません。列の最小幅を設定すると、ヘッダーテキストが変更されるまで問題が解決します。この場合、最小幅を0に設定し、変更された列のみを自動サイズ調整してから、最小幅を現在の幅に再度設定します。

編集:申し訳ありませんが、標準のリストビューではなく、サードパーティ製品のBetterListView(無料バージョンが利用可能)を使用していたことを忘れていました。標準のリストビュー列は最小幅をサポートしていないようです。優れた代替手段として、BetterListViewを強くお勧めします(はるかに優れた機能セットとパフォーマンス)。

0
Ben W.

アントン・ケドロフの答えが最善ですが、私の場合、50以上の列を持つリストビューがあり、この場合は頻繁にデータを更新しています。

To -2で設定することによる最初の方法

public void AutoUpdateColumnWidth(ListView lv)
{
    for (int i = 0; i <= lv.Columns.Count - 1; i++) {
        lv.Columns(i).Width = -2;
    }
}

私が使用した2番目の方法(複数の呼び出しでちらつきが少ない)

public void AutoUpdateColumnWidth(ListView lv)
{
    ListViewItem nLstItem = new ListViewItem(lv.Columns(0).Text);
    for (int i = 1; i <= lv.Columns.Count - 1; i++) {
        nLstItem.SubItems.Add(lv.Columns(i).Text);
    }
    v.Items.Add(nLstItem);
    lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
    lv.Items.RemoveAt(nLstItem.Index);
}
0
Jack Gajanan