假设我有以下 ListView:
<ListView ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListView.View>
<GridView>
<GridViewColumn Header="Something"
DisplayMemberBinding="{Binding Path=ShortText}" />
<GridViewColumn Header="Description"
DisplayMemberBinding="{Binding Path=VeryLongTextWithCRs}" />
<GridViewColumn Header="Something Else"
DisplayMemberBinding="{Binding Path=AnotherShortText}" />
</GridView>
</ListView.View>
</ListView>
我希望短文本列始终适合屏幕,长文本列使用剩余空间,必要时可自动换行。
这可能吗?
使用 GridListView 没有简单的方法来做到这一点,因为它不支持将列的宽度设置为“*”(填充剩余空间)。
这里讨论了如何通过使用 IValueConverter 将列的宽度设置为 TotalListWidth - SumOfColumnWidths
来伪造它另一方面,您是否考虑过使用 DataGrid 来代替?这将支持您正在寻找的布局类型,尽管这是一个相当重的控件。它也仅在 .NET 4 中原生 - 尽管您可以通过 WPF Toolkit 获得 3.5 的等效版本。
<Grid Name="dummygrid" Visibility="Hidden">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
<ColumnDefinition Width="0.1*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Name="dummywidth1"></Border>
<Border Grid.Column="1" Name="dummywidth2"></Border>
<Border Grid.Column="2" Name="dummywidth3"></Border>
<Border Grid.Column="3" Name="dummywidth4"></Border>
<Border Grid.Column="5" Name="dummywidth5"></Border>
</Grid>
<ListView Name="Installer_LV" Grid.Row="1" ItemContainerStyle="{StaticResource LV_ItemStyle}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" AlternationCount="2">
<ListView.View>
<GridView ColumnHeaderContainerStyle="{StaticResource LV_HeaderStyle}">
<GridViewColumn Width="{Binding ElementName=dummywidth1, Path=ActualWidth}" DisplayMemberBinding="{Binding DisplayName}" >
<GridViewColumn.Header>
<GridViewColumnHeader Tag="DisplayName" Click="InstallerLV_HeaderClick">Name</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Width="{Binding ElementName=dummywidth2, Path=ActualWidth}" DisplayMemberBinding="{Binding Publisher}">
<GridViewColumn.Header>
<GridViewColumnHeader Tag="Publisher" Click="InstallerLV_HeaderClick">Publisher</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Width="{Binding ElementName=dummywidth3, Path=ActualWidth}" DisplayMemberBinding="{Binding Version}">
<GridViewColumn.Header>
<GridViewColumnHeader Tag="Version" Click="InstallerLV_HeaderClick">Version</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Width="{Binding ElementName=dummywidth4, Path=ActualWidth}" DisplayMemberBinding="{Binding Size}">
<GridViewColumn.Header>
<GridViewColumnHeader Tag="Size" Click="InstallerLV_HeaderClick">Size</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Header="Action" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Height="38" Width="130" Style="{DynamicResource RoundedButton}" Content="{Binding Status}" Tag="{Binding ModuleId}" HorizontalAlignment="Center" VerticalAlignment="Center" Click="onActionClick"></Button>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
在上面的示例中,我使用了虚拟网格并分成 5 列,并使用绑定将该大小分配给“GridViewColum”
宽度=“{绑定元素名称=虚拟宽度4,路径=实际宽度}”
这样,当隐藏的虚拟网格列大小发生变化时,它也会反映在 gridview 列大小中。
在 GridViewColumns 上设置
Width="Auto"
。 但是,由于虚拟化,您可能会遇到一些自动调整大小的问题。
因此,长话短说,如果您想要准确地自动调整列大小,则需要在可见数据因虚拟化而发生变化时重新计算宽度。
这对我有用,对于没有明确设置宽度的任何列,将
Width
切换到 ActualWidth
,然后返回 NaN
。 仅当列表视图列不包含控件时,这才有效。 我通常在列表中的数据发生更改后调用此方法。
Public Shared Sub AutoResizeListView(lst As Windows.Controls.ListView)
Dim gv = DirectCast(lst.View, Windows.Controls.GridView)
For Each gvc In gv.Columns
If Double.IsNaN(gvc.Width) Then
gvc.Width = gvc.ActualWidth
gvc.Width = Double.NaN
End If
Next
End Sub
首先在列标题中设置名称,如下所示:
<GridViewColumn Header="Description" Width="350" x:Name="lvhDescription"/>
然后调整大小修改宽度。
Private Sub winMain_SizeChanged(sender As Object, e As SizeChangedEventArgs) Handles Me.SizeChanged
If Me.IsLoaded = False Then Exit Sub
lvhDescription.Width = e.NewSize.Width - 665
End Sub
我想提出另一种方法来调整具有最大元素宽度的每列的大小。 在循环的帮助下对每个列表视图项执行以下操作。
调整窗口大小事件后无需更改大小。
将 UnitWidth 保留为恒定字体宽度大小。
您还可以定义 SourceUpdated 事件的委托。
GridView gv = (myListView.View as GridView);
if (titleLen < c.Title.Length)
{
titleLen = c.Title.Length;
gv.Columns[0].Width = titleLen * UnitWidth;
}
if (cssLen < c.CSSName.Length)
{
cssLen = c.CSSName.Length;
gv.Columns[1].Width = cssLen * UnitWidth;
}
if (valueLen < c.Value.Length)
{
valueLen = c.Value.Length;
gv.Columns[2].Width = valueLen * UnitWidth;
}
尝试使用此代码,
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
double remainingSpace = mylistviewname.ActualWidth;
if (remainingSpace > 0)
{
(mylistviewname.View as GridView).Columns[1].Width = Math.Ceiling(remainingSpace / 3);
(mylistviewname.View as GridView).Columns[2].Width = Math.Ceiling(remainingSpace / 3);
(mylistviewname.View as GridView).Columns[3].Width = Math.Ceiling(remainingSpace / 3);
}
}
这里我使用 SizeChanged 事件,因此当窗口大小更改时,会触发此函数并更新 listviewheader 的宽度。我有 3 个列表视图标题,因此如果您有超过 3 个除以适当值的值,则除以 3。
<ListView ScrollViewer.VerticalScrollBarVisibility="Auto" Name="someList">
<ListView.View>
<GridView>
<GridViewColumn Width={Binding ElementName=someList, Path=ActualWidth/3} Header="Something" DisplayMemberBinding="{Binding Path=ShortText}" />
<GridViewColumn Width={Binding ElementName=someList, Path=ActualWidth/3} Header="Description" DisplayMemberBinding="{Binding Path=VeryLongTextWithCRs}" />
<GridViewColumn Width={Binding ElementName=someList, Path=ActualWidth/3} Header="Something Else" DisplayMemberBinding="{Binding Path=AnotherShortText}" />
</GridView>
</ListView.View>
</ListView>
使用@joee解决方案,它会产生“ArgumentOutOfRangeException”:
System.ArgumentOutOfRangeException:'索引超出范围。必须为非负数且小于集合的大小。 Arg_ParamName_Name'
试试这个:
private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
{
double remainingSpace = SomeListViewName.ActualWidth;
var gridView = (GridView)OrderListView.View;
if (remainingSpace > 0)
{
foreach (var column in gridView.Columns)
{
column.Width = Math.Ceiling(remainingSpace / 12);
}
}
}
就我而言,我有 12 列。因此下降了 12