WPF DataGrid AutoSize问题

FA *_*ers 13 c# wpf datagrid

我最近一直试图在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>
Run Code Online (Sandbox Code Playgroud)

Fre*_*lad 1

是的,我也遇到过,应该是bug。问题实际上不是包裹本身,而是一旦单元格变得比原来小,那么 DataGrid 的高度将不会更新,直到它因任何原因调整大小(更改窗口大小或其他原因)。我没有很好的解决这个问题的方法,但这里有一些解决方法。

更新

优化版本,使用 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>
Run Code Online (Sandbox Code Playgroud)

添加附加属性

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);
    }
Run Code Online (Sandbox Code Playgroud)

为每个将 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;
    }
    //...
}
Run Code Online (Sandbox Code Playgroud)