Подтвердить что ты не робот

Изменение размера столбцов GridView внутри ListView

У меня есть элемент управления ListView WPF с GridView. Я хочу изменить размер столбцов GridView при изменении содержимого столбцов.

У меня есть несколько различных наборов данных, но когда я меняю один на другой, размер каждого столбца соответствует предыдущим данным. Я бы хотел обновить динамически. Как я могу это сделать?

4b9b3361

Ответ 1

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

public void AutoSizeColumns()
{
    GridView gv = listView1.View as GridView;
    if (gv != null)
    {
        foreach (var c in gv.Columns)
        {
            // Code below was found in GridViewColumnHeader.OnGripperDoubleClicked() event handler (using Reflector)
            // i.e. it is the same code that is executed when the gripper is double clicked
            if (double.IsNaN(c.Width))
            {
                c.Width = c.ActualWidth;
            }
            c.Width = double.NaN;
        }
    }
}

Ответ 2

Создавая ответ на вопрос Oskars, здесь приведен пример поведения для автоматического изменения столбцов при изменении содержимого.

 /// <summary>
 /// A <see cref="Behavior{T}"/> implementation which will automatically resize the automatic columns of a <see cref="ListView">ListViews</see> <see cref="GridView"/> to the new content.
 /// </summary>
 public class GridViewColumnResizeBehaviour : Behavior<ListView>
 {
      /// <summary>
      /// Listens for when the <see cref="ItemsControl.Items"/> collection changes.
      /// </summary>
      protected override void OnAttached()
      {
          base.OnAttached();

          var listView = AssociatedObject;
          if (listView == null)
              return;

          AddHandler(listView.Items);
      }

      private void AddHandler(INotifyCollectionChanged sourceCollection)
      {
          Contract.Requires(sourceCollection != null);

          sourceCollection.CollectionChanged += OnListViewItemsCollectionChanged;
      }

      private void RemoveHandler(INotifyCollectionChanged sourceCollection)
      {
          Contract.Requires(sourceCollection != null);

          sourceCollection.CollectionChanged -= OnListViewItemsCollectionChanged;
      }

      private void OnListViewItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
      {
          var listView = AssociatedObject;
          if (listView == null)
              return;

          var gridView = listView.View as GridView;
          if (gridView == null)
              return;

          // If the column is automatically sized, change the column width to re-apply automatic width
          foreach (var column in gridView.Columns.Where(column => Double.IsNaN(column.Width)))
          {
               Contract.Assume(column != null);
               column.Width = column.ActualWidth;
               column.Width = Double.NaN;
          }
      }

      /// <summary>
      /// Stops listening for when the <see cref="ItemsControl.Items"/> collection changes.
      /// </summary>
      protected override void OnDetaching()
      {
          var listView = AssociatedObject;
          if (listView != null)
              RemoveHandler(listView.Items);

          base.OnDetaching();
      }
 }

Ответ 3

Нет ли способа привязки к ActualWidth столбца? Что-то вроде:

<GridViewColumn x:Name="column1" Width="{Binding ElementName=column1, Path=ActualWidth}" />

Я пробовал это, и он работает только в первый раз, кажется. Ошибка привязки.

Ответ 4

Если, как и я, вы стары и предпочитаете VB.NET, то здесь код Oskars:

Public Sub AutoSizeColumns()
    Dim gv As GridView = TryCast(Me.listview1.View, GridView)
    If gv IsNot Nothing Then
        For Each c As GridViewColumn In gv.Columns
            If Double.IsNaN(c.Width) Then
                c.Width = c.ActualWidth
            End If
            c.Width = Double.NaN
        Next
    End If
End Sub

Это отлично работает в WPF, и, наконец, кто-то справился с этим. Спасибо Оскару.

Ответ 5

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

Graphics graphics = this.CreateGraphics();
SizeF textSize = graphics.MeasureString("How long am I?", this.Font);

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