C# 强制调整 ListView 内 GridView 列的大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/845269/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:55:05  来源:igfitidea点击:

Force resize of GridView columns inside ListView

c#.netwpflistview

提问by

I have a ListViewWPF control with a GridView. I'd like to resize the GridViewcolumns when the content of the columns changes.

我有一个ListView带有GridView. GridView当列的内容发生变化时,我想调整列的大小。

I have several distinct data sets but when I change from one to another, the size of each columns fits the previous data. I'd like to update dynamically. How can I do that?

我有几个不同的数据集,但是当我从一个更改为另一个时,每列的大小都适合以前的数据。我想动态更新。我怎样才能做到这一点?

回答by Richard

You could measure the longest string in pixels and then adjust the column widths accordingly:

您可以以像素为单位测量最长的字符串,然后相应地调整列宽:

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

If you create an algorithm for sizing each column as a ratio of these lengths, you should get a good result.

如果您创建一个算法来将每列的大小设置为这些长度的比率,您应该会得到一个很好的结果。

回答by Oskar

Finally, some results on this one. I've found a way to do the same auto-sizing that is done initially and when the gripper on a column header is double clicked.

最后,关于这个的一些结果。我找到了一种方法来执行与最初和双击列标题上的夹具时相同的自动调整大小。

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;
        }
    }
}

回答by Thia

Isn't there a way to bind to the ActualWidthof the column? Something like :

没有办法绑定到ActualWidth列的 吗?就像是 :

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

I have tried this and it works only the first time, it seems. No binding error.

我试过这个,它似乎只在第一次工作。没有绑定错误。

回答by Lukazoid

Building on top of Oskars answer, here is a blend behavior to automatically size the columns when the content changes.

在 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();
      }
 }

回答by Richard Harrison

If like me you are old and prefer VB.NET then here's Oskars code:

如果像我一样你年纪大了并且更喜欢 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

This works great in WPF, finally someone has worked this out. Thanks Oskar.

这在 WPF 中效果很好,终于有人解决了这个问题。谢谢奥斯卡。