WPF DataGrid AutoSize 问题
Posted
技术标签:
【中文标题】WPF DataGrid AutoSize 问题【英文标题】:WPF DataGrid AutoSize Issue 【发布时间】:2011-05-04 01:29:57 【问题描述】:我最近一直在尝试让文本换行在 WPF (C/4.0) DataGrid 中工作,无论我实施哪种解决方案(都在模板内使用某种形式的 TextBlock 并进行换行),它都会混淆自动高度并导致网格底部有过多的空白(为了可见性而设置为黄色)。
我的代码:(注释代码是文本换行的替代解决方案,但仍会导致空间过大)
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid Grid.Row="0" AutoGenerateColumns="False" ColumnWidth="*" Name="dgFamilyHistories" IsReadOnly="True"
HorizontalScrollBarVisibility="Disabled"
ItemsSource="Binding Path=Patient.FamilyHistories" RowDetailsVisibilityMode="Visible"
GridLinesVisibility="All">
<DataGrid.Resources>
<Style TargetType="x:Type DataGridRow">
<Setter Property="Height" Value="Auto"/>
</Style>
<!--<Style TargetType="x:Type DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="x:Type DataGridCell">
<Border Name="border">
<ContentControl Content="TemplateBinding Content">
<ContentControl.ContentTemplate>
<DataTemplate>
<DockPanel>
<TextBlock TextWrapping="WrapWithOverflow" TextTrimming="CharacterEllipsis"
Width="Auto" Height="Auto" Text="Binding Text"/>
</DockPanel>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>-->
</DataGrid.Resources>
<DataGrid.Background>
<SolidColorBrush Color="Yellow" />
</DataGrid.Background>
<DataGrid.Columns>
<DataGridTextColumn Header="Date" Binding="Binding DateEntered, StringFormat=0:dd/MM/yyyy" Width="85"/>
<!--<DataGridTextColumn Header="Relation" Binding="Binding Relation"/>-->
<DataGridTemplateColumn Header="Relation">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock TextTrimming="CharacterEllipsis" TextWrapping="Wrap" Text="Binding Path=Relation"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!--<DataGridTextColumn Header="Illness" Binding="Binding Illness"/>-->
<DataGridTemplateColumn Header="Illness">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock TextTrimming="CharacterEllipsis" TextWrapping="Wrap" Text="Binding Path=Illness"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!--<DataGridTextColumn Header="Health" Binding="Binding Health"/>-->
<DataGridTemplateColumn Header="Health">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock TextTrimming="CharacterEllipsis" TextWrapping="Wrap" Text="Binding Path=Health"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Birth Date" Binding="Binding DateOfBirth, StringFormat=0:dd/MM/yyyy" Width="85"/>
<DataGridTextColumn Header="Death Date" Binding="Binding DateOfDeath, StringFormat=0:dd/MM/yyyy" Width="85"/>
<!--<DataGridTextColumn Header="Death Cause" Binding="Binding CauseOfDeath"/>-->
<DataGridTemplateColumn Header="Death Cause">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock TextTrimming="CharacterEllipsis" TextWrapping="Wrap" Text="Binding Path=CauseOfDeath"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Age" Binding="Binding Age" Width="50"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Label Name="lblDetails" Content="Binding Path=Comments" ContentStringFormat="Comments: 0" Margin="15,0,0,0"/>
<DataTemplate.Triggers>
<DataTrigger Binding="Binding Path=Comments, Converter=Converters:IsNullStringConverter" Value="True">
<Setter TargetName="lblDetails" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
<DockPanel Grid.Row="1" Background="Blue">
</DockPanel>
</Grid>
【问题讨论】:
【参考方案1】:是的,我也遇到过,一定是bug。问题实际上不在于 Wrapping 本身,而在于一旦单元格变得比原来更小,那么 DataGrid 的高度将不会更新,直到由于任何原因(更改 Window 的大小或其他)调整它的大小。我对这个问题没有很好的解决方案,但这里有一些解决方法。
更新
优化版本,使用 DataGridColumn 代替 TextBlocks。使用附加属性 WrapColumn(默认为 false)来了解包装的列。
Xaml。为每个包装列添加 local:MainWindow.WrapColumn="True"。
<DataGridTemplateColumn Header="Health"
local:MainWindow.WrapColumn="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock TextTrimming="CharacterEllipsis"
TextWrapping="Wrap"
Text="Binding Path=Health"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
添加附加属性
public partial class MainWindow : Window
private static readonly DependencyProperty WrapColumnProperty =
DependencyProperty.RegisterAttached("WrapColumn",
typeof(bool),
typeof(MainWindow));
public static void SetWrapColumn(DependencyObject element, bool value)
element.SetValue(WrapColumnProperty, value);
public static bool GetWrapColumn(DependencyObject element)
return (bool)element.GetValue(WrapColumnProperty);
为每个将 WrapColumn 设置为 true 的 DataGridColumn 添加一个监听器,以监听 ActualWidth 的变化
public MainWindow()
InitializeComponent();
DependencyPropertyDescriptor dependencyPropertyDescriptor =
DependencyPropertyDescriptor.FromProperty(DataGridColumn.ActualWidthProperty, typeof(DataGridColumn));
if (dependencyPropertyDescriptor != null)
foreach (DataGridColumn column in c_dataGrid.Columns)
if (GetWrapColumn(column) == true)
dependencyPropertyDescriptor.AddValueChanged(column, DataGridColumn_ActualWidthChanged);
void DataGridColumn_ActualWidthChanged(object sender, EventArgs e)
c_dataGrid.Width = c_dataGrid.ActualWidth - 1;
EventHandler eventHandler = null;
eventHandler = new EventHandler(delegate
c_dataGrid.Width = double.NaN;
c_dataGrid.LayoutUpdated -= eventHandler;
);
c_dataGrid.LayoutUpdated += eventHandler;
//...
【讨论】:
此解决方案有效,但在使用流文档打印时,自动尺寸仍然会混淆。如果流文档触发调整大小,则其高度显示正确,但所有列都被压扁。 看到你批准和不批准它一段时间后,所以我认为有些东西不是在玩球。所以列最终宽度最小,或者有什么影响? 差不多,基本上我将网格放入流文档中,然后打印。基本上发生的事情是,一旦流文档超过一页,它上面的第一个数据网格就会被弄乱。 (整体网格的宽度正确,标题也是如此,但脚趾单元格都向左挤压。我会尝试发布屏幕截图。 对不起,让我修改一下,网格的宽度是正确的,但标题和单元格向左挤压(可能是最小宽度) 这里是屏幕截图的链接www2.picturepush.com/photo/a/4483245/img/4483245.jpg【参考方案2】:Use this way, to expand your datagrid with proper height and width
<my:DataGridTemplateColumn Header="DynamicResource name" Width="*"
CanUserSort="True" SortMemberPath="Name"
HeaderStyle="StaticResource StaffDgColoumnHeaderStyle">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Style="StaticResource RowTextblockStyle" >`enter code here`
<Hyperlink>
<TextBlock Text="Binding Path=Name" ToolTip="Binding Name"
TextWrapping="NoWrap" TextTrimming="CharacterEllipsis"/>
</Hyperlink>
</TextBlock>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
<my:DataGridTemplateColumn Header="DynamicResource sft" Width="*"
CanUserSort="True" SortMemberPath="ShiftName"
HeaderStyle="StaticResource StaffDgColoumnHeaderStyle">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="Binding ShiftName" ToolTip="Binding ShiftName"
Style="StaticResource RowTextblockStyle"/>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
See Width ="*" Or Use Width ="Auto" or Width = "20*" as per as your requirement.
【讨论】:
以上是关于WPF DataGrid AutoSize 问题的主要内容,如果未能解决你的问题,请参考以下文章
wpf datagrid怎么得到焦点?用datagrid.focus()不行