C# 强制调整ListView中GridView列的大小
我有一个带有GridView的ListView WPF控件。我想在列的内容更改时调整GridView列的大小C# 强制调整ListView中GridView列的大小,c#,.net,wpf,listview,C#,.net,Wpf,Listview,我有一个带有GridView的ListView WPF控件。我想在列的内容更改时调整GridView列的大小 我有几个不同的数据集,但是当我从一个数据集更改到另一个数据集时,每列的大小都与以前的数据相匹配。我想动态更新。如何才能做到这一点?您可以测量以像素为单位的最长字符串,然后相应地调整列宽: Graphics graphics = this.CreateGraphics(); SizeF textSize = graphics.MeasureString("How long am I?",
我有几个不同的数据集,但是当我从一个数据集更改到另一个数据集时,每列的大小都与以前的数据相匹配。我想动态更新。如何才能做到这一点?您可以测量以像素为单位的最长字符串,然后相应地调整列宽:
Graphics graphics = this.CreateGraphics();
SizeF textSize = graphics.MeasureString("How long am I?", this.Font);
如果您创建一个算法,根据这些长度的比率调整每列的大小,您应该会得到一个好的结果。您可以测量以像素为单位的最长字符串,然后相应地调整列宽:
Graphics graphics = this.CreateGraphics();
SizeF textSize = graphics.MeasureString("How long am I?", this.Font);
如果您创建一个算法,根据这些长度的比率来调整每个列的大小,您应该会得到一个好的结果。最后,在这个问题上会有一些结果。我已经找到了一种方法,可以在双击列标题上的夹持器时自动调整大小
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;
}
}
}
最后,本文给出了一些结果。我已经找到了一种方法,可以在双击列标题上的夹持器时自动调整大小
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;
}
}
}
有没有办法绑定到列的实际宽度?比如:
<GridViewColumn x:Name="column1" Width="{Binding ElementName=column1, Path=ActualWidth}" />
我已经试过了,但它似乎只是第一次起作用。没有绑定错误。是否有方法绑定到列的实际宽度?比如:
<GridViewColumn x:Name="column1" Width="{Binding ElementName=column1, Path=ActualWidth}" />
我已经试过了,但它似乎只是第一次起作用。没有绑定错误。建立在奥斯卡答案之上,这里有一个混合行为,可以在内容更改时自动调整列的大小
/// <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();
}
}
在Oskar answer的基础上,这里有一个混合行为,可以在内容更改时自动调整列的大小
/// <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();
}
}
如果你像我一样老了,喜欢VB.NET,那么下面是奥斯卡代码:
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中非常有效,终于有人解决了这个问题。谢谢奥斯卡。如果你像我一样老了,更喜欢VB.NET,那么奥斯卡代码如下:
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中非常有效,终于有人解决了这个问题。谢谢奥斯卡。我也有同样的问题。更改数据源,列宽不会调整大小。我很乐意设置源代码并调用AutoSizeColumns方法或类似方法。我也有同样的问题。更改数据源,列宽不会调整大小。我很乐意设置源代码并调用AutoSizeColumns方法或类似方法。我也尝试过:Width={Binding Path=ActualWidth,RelativeSource={x:Static RelativeSource.Self}}}是的,将ActualWidth复制到Width,这将永远是预期的宽度。第一次禁用自动调整大小。然后,实际宽度再也不会改变,因此预期宽度也不会改变。我也尝试过:宽度={Binding Path=ActualWidth,RelativeSource={x:Static RelativeSource.Self}}}是的,将实际宽度复制到宽度,这将永远是预期宽度。第一次禁用自动调整大小。实际宽度将不再改变,因此预期宽度也不会改变。很好的解决方案。谢谢,很好的解决方案。谢谢。此行为没有考虑到在计算新的实际宽度之前可能需要一些时间。因此,实际宽度可能仍然太小,无法容纳内容物。@Danielku15您发现了吗?一个小样本将非常好,这样我就可以解决这个问题。我有一个绑定到ObservableCollection的ListView。我的CellTemplate中有一个控件是40x40pt。附加该行为将执行OnListViewItemsCollectionChanged方法,但在我的示例中,实际宽度仍然太小。结果是:它被裁剪了。似乎在执行处理程序时layoutprocess没有运行。与@Danielku15类似,我有一个ListViewBehavior类,它在ListView.ItemsChanged事件处理程序中实现了ActualWidth、Double.NaN更改。将绑定的源属性设置为新的项集合时,会计算自动列,但会在稍后的未知时间进行,因此无法调整填充列的大小&列溢出ListView宽度。删除这些行和自动列是按预期计算的,并且完全符合ListView宽度,但它们不是按新内容计算的。此行为没有考虑到在计算新的实际宽度之前可能需要一段时间。因此,实际宽度可能仍然太小,无法容纳内容物。@Danielku15您发现了吗?一个小样本将非常好,这样我就可以解决这个问题。我有一个绑定到ObservableCollection的ListView。我的CellTemplate中有一个控件是40x40pt。附加该行为将执行OnListViewItemsCollectionChanged方法,但在我的示例中,实际宽度仍然太小。结果是:它被裁剪了。似乎在执行处理程序时layoutprocess没有运行。与@Danielku15类似,我有一个ListViewBehavior类,它在ListView.ItemsChanged事件处理程序中实现了ActualWidth、Double.NaN更改。将绑定源属性设置为新coll时 项的节,自动列是计算出来的,但在以后未知的时间,所以我无法调整填充列的大小&列溢出了ListView的宽度。删除这些行和自动列会在需要时进行计算,并与ListView宽度完全匹配,但不会根据新内容进行计算。