ListView AutoResizeColumns на основе как содержимого столбца, так и заголовка - программирование
Подтвердить что ты не робот

ListView AutoResizeColumns на основе как содержимого столбца, так и заголовка

мы используем эти два метода для настройки длины столбца на основе содержимого столбца и заголовка.

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

Но как настроить на основе обоих? то есть отрегулировать до самой длинной длины для содержимого заголовка и столбца.

4b9b3361

Ответ 1

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

Ответ 2

Как ответил здесь, вызов обоих параметров изменения размера выполняет задание:

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

Ответ 3

Это то, что я использую для настройки ширины столбца как для содержимого, так и для заголовка:

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

Можно действительно использовать 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% для остальных.

Это как-то бедный человек быстрой реализации.: -)

Ответ 5

В моем случае я делаю это с помощью следующих шагов (для двух столбцов данных):

  • Создание объекта ColumnHeader для каждого столбца.
  • Установка размера с помощью функции AutoResize на основе HeaderSize (в обоих столбцах)
  • Сохраните это значение в переменной Integer
  • Установка размера с помощью AutoResize на основе ColumnContent (в обоих столбцах)
  • Обновление значения каждой переменной Integer с помощью критериев Max между старым значением и новым значением (для каждого столбца).
  • Установка размера ширины столбца для каждого объекта 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

Ответ 6

Здесь С# решение, которое можно использовать для любого ListView. Предполагается, что количество столбцов и заголовков столбцов не изменится для любого вида списка. Избавьтесь от словаря 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();
    }

Ответ 7

Ответ Антона Кедрова - лучший, но в моем случае у меня есть список с более чем 50 столбцами, и я часто обновляю его данные. В этом случае я вижу listview this.AutoResizeColumns выполняет гораздо более быструю работу, поэтому я пишу это решение также

Первый метод, установив с параметром -2

public void AutoUpdateColumnWidth(ListView lv)
{
    for (int i = 0; i <= lv.Columns.Count - 1; i++) {
        lv.Columns(i).Width = -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);
}

Ответ 8

Это просто (хотя мне потребовалось некоторое время, чтобы понять)...

Мы знаем, что ширина должна быть не меньше, чем заголовки столбцов, поэтому мы видим весь текст заголовка. Кроме того, ширина может расширяться больше для размещения содержимого. Следовательно, мы делаем следующее:

  • Автосортировать столбцы в заголовок.
  • Итерируйте по столбцам и задайте минимальное свойство ширины для каждого столбца текущей ширины столбца (что гарантирует, что ваши столбцы никогда не станут слишком маленькими, чтобы увидеть заголовок).
  • Отныне автоматически сортируйте столбцы по контенту.

Нет необходимости отслеживать ширину отдельно и reset их, как предлагают другие плакаты. Установка минимальной ширины столбца разрешает проблему до тех пор, пока текст заголовка не будет изменен, и в этом случае вы установите минимальную ширину равным 0, автоматически настройте только измененный столбец, а затем снова установите минимальную ширину на текущую ширину.

EDIT: Мои извинения, я забыл, что я не использовал стандартный список, но вместо этого сторонний продукт BetterListView (доступна бесплатная версия). Стандартные столбцы listview не поддерживают минимальную ширину. Я рекомендую BetterListView как отличную альтернативу (намного лучший набор функций и производительность).