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 右键菜单加多个选项?

wpf datagrid怎么得到焦点?用datagrid.focus()不行

wpf datagrid 怎么增加数据行

WPF MVVM DataGrid Button Command绑定

wpf datagrid 单元格如何默认单击一次点中

WPF 基础控件之 DataGrid 样式