如何在 WPF 中自动调整和右对齐 GridViewColumn 数据?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/560581/
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
How to autosize and right-align GridViewColumn data in WPF?
提问by Edward Tanguay
How can I:
我怎样才能:
- right-align the text in the ID column
- make each of the columns auto size according to the text length of the cell with the longest visible data?
- 右对齐 ID 列中的文本
- 根据具有最长可见数据的单元格的文本长度使每一列自动调整大小?
Here is the code:
这是代码:
<ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding Id}" Width="40"/>
<GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="100" />
<GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}"/>
</GridView>
</ListView.View>
</ListView>
partial answer:
部分答案:
Thanks Kjetil, the GridViewColumn.CellTemplate works well and the Auto Width works of course but when the ObservativeCollection "Collection" is updated with longer-than-column-width data, the column sizes do not update themselves so that is only a solution for the initial display of data:
感谢 Kjetil,GridViewColumn.CellTemplate 运行良好,自动宽度当然可以运行,但是当 ObservativeCollection“Collection”更新为长于列宽的数据时,列大小不会自行更新,因此这只是解决数据的初始显示:
<ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Id}" TextAlignment="Right" Width="40"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="Auto" />
<GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}" Width="Auto"/>
</GridView>
</ListView.View>
</ListView>
回答by Kjetil Watnedal
To make each of the columns autosize you can set Width="Auto" on the GridViewColumn.
要使每一列自动调整大小,您可以在 GridViewColumn 上设置 Width="Auto"。
To right-align the text in the ID column you can create a cell template using a TextBlock and set the TextAlignment. Then set the ListViewItem.HorizontalContentAlignment (using a style with a setter on the ListViewItem) to make the cell template fill the entire GridViewCell.
要右对齐 ID 列中的文本,您可以使用 TextBlock 创建单元格模板并设置 TextAlignment。然后设置 ListViewItem.HorizontalContentAlignment(在 ListViewItem 上使用带有 setter 的样式)使单元格模板填充整个 GridViewCell。
Maybe there is a simpler solution, but this should work.
也许有一个更简单的解决方案,但这应该有效。
Note:the solution requires both HorizontalContentAlignment=Stretchin Window.Resources and TextAlignment=Rightin the CellTemplate.
注意:该解决方案需要Window.Resources 中的HorizontalContentAlignment=Stretch和CellTemplate 中的TextAlignment=Right。
<Window x:Class="WpfApplication6.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</Window.Resources>
<Grid>
<ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" Width="40">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Id}" TextAlignment="Right" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="Auto" />
<GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}" Width="Auto"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
回答by RandomEngy
If the width of the contents changes, you'll have to use this bit of code to update each column:
如果内容的宽度发生变化,则必须使用这段代码来更新每一列:
private void ResizeGridViewColumn(GridViewColumn column)
{
if (double.IsNaN(column.Width))
{
column.Width = column.ActualWidth;
}
column.Width = double.NaN;
}
You'd have to fire it each time the data for that column updates.
每次该列的数据更新时,您都必须触发它。
回答by Rolf Wessels
If your listview is also re-sizing then you can use a behavior pattern to re-size the columns to fit the full ListView width. Almost the same as you using grid.column definitions
如果您的列表视图也在调整大小,那么您可以使用行为模式来调整列的大小以适应整个 ListView 宽度。几乎与您使用 grid.column 定义相同
<ListView HorizontalAlignment="Stretch"
? ? ? ? ? Behaviours:GridViewColumnResize.Enabled="True">
? ? ? ? <ListViewItem></ListViewItem>
? ? ? ? <ListView.View>
? ? ? ? ? ? <GridView>
? ? ? ? ? ? ? ? <GridViewColumn ?Header="Column *"
? ? ?? ? ?? ? ??? ?? ? ? ? ? ? ? ? Behaviours:GridViewColumnResize.Width="*" >
? ? ? ? ? ? ? ? ? ? <GridViewColumn.CellTemplate>
? ? ? ? ? ? ? ? ? ? ? ? <DataTemplate>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <TextBox HorizontalAlignment="Stretch" Text="Example1" />
? ? ? ? ? ? ? ? ? ? ? ? </DataTemplate>
? ? ? ? ? ? ? ? ? ? </GridViewColumn.CellTemplate>
See the following link for some examples and link to source code http://lazycowprojects.tumblr.com/post/7063214400/wpf-c-listview-column-width-auto
请参阅以下链接以获取一些示例和源代码链接 http://lazycowprojects.tumblr.com/post/7063214400/wpf-c-listview-column-width-auto
回答by user1333423
I have created the following class and used across the application wherever required in place of GridView
:
我创建了以下类,并在需要的地方在整个应用程序中使用GridView
:
/// <summary>
/// Represents a view mode that displays data items in columns for a System.Windows.Controls.ListView control with auto sized columns based on the column content
/// </summary>
public class AutoSizedGridView : GridView
{
protected override void PrepareItem(ListViewItem item)
{
foreach (GridViewColumn column in Columns)
{
// Setting NaN for the column width automatically determines the required
// width enough to hold the content completely.
// If the width is NaN, first set it to ActualWidth temporarily.
if (double.IsNaN(column.Width))
column.Width = column.ActualWidth;
// Finally, set the column with to NaN. This raises the property change
// event and re computes the width.
column.Width = double.NaN;
}
base.PrepareItem(item);
}
}
回答by paparazzo
Since I had an ItemContainerStyle I had to put the HorizontalContentAlignment in the ItemContainerStyle
因为我有一个 ItemContainerStyle 我不得不把 HorizontalContentAlignment 放在 ItemContainerStyle
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=FieldDef.DispDetail, Mode=OneWay}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
....
回答by jv_
I liked user1333423's solution except that it always re-sized every column; i needed to allow some columns to be fixed width. So in this version columns with a width set to "Auto" will be auto-sized and those set to a fixed amount will not be auto-sized.
我喜欢 user1333423 的解决方案,只是它总是重新调整每一列的大小;我需要允许某些列具有固定宽度。因此,在此版本中,宽度设置为“自动”的列将自动调整大小,而设置为固定数量的列将不会自动调整大小。
public class AutoSizedGridView : GridView
{
HashSet<int> _autoWidthColumns;
protected override void PrepareItem(ListViewItem item)
{
if (_autoWidthColumns == null)
{
_autoWidthColumns = new HashSet<int>();
foreach (var column in Columns)
{
if(double.IsNaN(column.Width))
_autoWidthColumns.Add(column.GetHashCode());
}
}
foreach (GridViewColumn column in Columns)
{
if (_autoWidthColumns.Contains(column.GetHashCode()))
{
if (double.IsNaN(column.Width))
column.Width = column.ActualWidth;
column.Width = double.NaN;
}
}
base.PrepareItem(item);
}
}
回答by Azzy Elvul
I know that this is too late but here is my approach:
我知道这为时已晚,但这是我的方法:
<GridViewColumn x:Name="GridHeaderLocalSize" Width="100">
<GridViewColumn.Header>
<GridViewColumnHeader HorizontalContentAlignment="Right">
<Grid Width="Auto" HorizontalAlignment="Right">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Local size" TextAlignment="Right" Padding="0,0,5,0"/>
</Grid>
</GridViewColumnHeader>
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Width="{Binding ElementName=GridHeaderLocalSize, Path=Width, FallbackValue=100}" HorizontalAlignment="Right" TextAlignment="Right" Padding="0,0,5,0" Text="Text" >
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
The main idea is to bind the width of the cellTemplete element to the width of the ViewGridColumn. Width=100 is default width used until first resize. There isn't any code behind. Everything is in xaml.
主要思想是将 cellTemplete 元素的宽度绑定到 ViewGridColumn 的宽度。Width=100 是第一次调整大小之前使用的默认宽度。后面没有任何代码。一切都在 xaml 中。
回答by Andrei Rogobete
I created a function for updating GridView column headers for a list and call it whenever the window is re-sized or the listview updates it's layout.
我创建了一个用于更新列表的 GridView 列标题的函数,并在窗口重新调整大小或列表视图更新其布局时调用它。
public void correctColumnWidths()
{
double remainingSpace = myList.ActualWidth;
if (remainingSpace > 0)
{
for (int i = 0; i < (myList.View as GridView).Columns.Count; i++)
if (i != 2)
remainingSpace -= (myList.View as GridView).Columns[i].ActualWidth;
//Leave 15 px free for scrollbar
remainingSpace -= 15;
(myList.View as GridView).Columns[2].Width = remainingSpace;
}
}
回答by Adam Tegen
I had trouble with the accepted answer (because I missed the HorizontalAlignment=Stretch portion and have adjusted the original answer).
我在接受答案时遇到了麻烦(因为我错过了 HorizontalAlignment=Stretch 部分并调整了原始答案)。
This is another technique. It uses a Grid with a SharedSizeGroup.
这是另一种技术。它使用带有 SharedSizeGroup 的 Grid。
Note:the Grid.IsSharedScope=trueon the ListView.
注:该Grid.IsSharedScope =真上ListView控件。
<Window x:Class="WpfApplication6.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}" Grid.IsSharedSizeScope="True">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" Width="40">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="IdColumn"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Right" Text={Binding Path=Id}"/>
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="Auto" />
<GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}" Width="Auto"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
回答by StriderWaR
This is your code
这是你的代码
<ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding Id}" Width="40"/>
<GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="100" />
<GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}"/>
</GridView>
</ListView.View>
</ListView>
Try this
尝试这个
<ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Id}" Width="Auto">
<GridViewColumnHeader Content="ID" Width="Auto" />
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding FirstName}" Width="Auto">
<GridViewColumnHeader Content="First Name" Width="Auto" />
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding LastName}" Width="Auto">
<GridViewColumnHeader Content="Last Name" Width="Auto" />
</GridViewColumn
</GridView>
</ListView.View>
</ListView>