Force resize of GridView columns inside ListView
Solution 1
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;
}
}
}
Solution 2
Building on top of Oskars answer, here is a blend behavior to automatically size the columns when the content changes.
/// <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();
}
}
Solution 3
Isn't there a way to bind to the ActualWidth
of the column? Something like :
<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.
Solution 4
If like me you are old and prefer VB.NET then here's Oskars code:
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.
Related videos on Youtube
Dave Clemmer
I enjoy coding like an excellent beer. My particular passion and experience lies in the realm of modeling and code generation. In the late 80s and early 90s, I was involved in early modeling and code generation tools that reached the marketplace, including a tool that modeled FORTRAN programs and generated FORTRAN for parallel supercomputer architectures, and a tool that managed Shlaer-Mellor models and generated C++ code. Over the years, I have applied Shlaer-Mellor, UML, and custom modeling and various code generation techniques to greatly benefit the development of enterprise applications. My current passion and endeavor is to foster the evolution of model oriented development. In particular, I am passionate about evolving the Mo+ model oriented programming language and related model driven development tools, with as much community input as possible to achieve higher levels in the ability to create and maintain code. The open source site is at moplus.codeplex.com, and the Mo+ membership site is at modelorientedplus.com.
Updated on April 17, 2022Comments
-
Dave Clemmer about 2 years
I have a
ListView
WPF control with aGridView
. I'd like to resize theGridView
columns when the content of the columns changes.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?
-
Drew Noakes almost 15 yearsI have the same issue. Change the data source, and the column widths don't resize. I'd be happy to set the source and call an AutoSizeColumns method or similar.
-
-
Thia almost 15 yearsI have also tried : Width="{Binding Path=ActualWidth, RelativeSource={x:Static RelativeSource.Self}}"
-
ygoe over 11 yearsYeah, you copy ActualWidth over to Width, which is then the intended width forever. The auto-sizing is disabled at the first time. ActualWidth then never changes again, so the intended width won't either.
-
AH. over 9 yearsGreat solution. Thanks.
-
Danielku15 about 9 yearsThis behavior does not take into account that it might take some time until the new
ActualWidth
is calculated. Therefore it might happen thatActualWidth
still is too small to fit the contents. -
Lukazoid about 9 years@Danielku15 Are you finding that is happening? A small sample would be great so I can work towards fixing this problem.
-
Danielku15 about 9 yearsI have a ListView bound to an ObservableCollection. I have a control in my CellTemplate that is 40x40pt. Attaching the Behavior executes the OnListViewItemsCollectionChanged method, but the ActualWidth is still too small (25pt in my case). The result: it's cropped. It seems the layoutprocess did not run when the handler is executed.
-
OhBeWise over 8 yearsSimilar to @Danielku15 I have a ListViewBehavior class that implements the ActualWidth, Double.NaN change in the ListView.ItemsChanged event handler. When setting the bound source property to a new collection of items, the Auto columns are calculated but at some later unknown time (so I can't resize a Fill column & columns overflow the ListView width). Remove those lines and Auto columns are calculated when expected and fit the ListView width exactly, but they aren't calculated to the new content.