【问题标题】:Solving DataGrid inconsistent column width sizing解决 DataGrid 列宽大小不一致的问题
【发布时间】:2015-03-12 13:49:45
【问题描述】:

在我们的应用程序中,我们使用数据网格来布局填充了模板化内容和按钮的行,但是会间歇性地出现一个问题,即某些列有时会将自身调整为列的最小宽度,有时会调整到列标题内容的宽度。这似乎与设置 itemssource 的时间以及发生加载事件的时间有关,但我无法确定。

错误行为示例

正确行为示例

itemssource 绑定到 viewmodel 上的 ObservableCollection,它使用 async 和 await 关键字和数据服务填充异步。

我试图通过在初始化时隐藏所有列来解决此问题,然后一旦设置了 itemssource 并已调用 isloaded 将所有列设置回初始可见性,这似乎有一些影响,但没有解决问题完全。

列定义的 xaml

<Style x:Key="MainDataGridColumnHeader" TargetType="{x:Type DataGridColumnHeader}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                <TextBlock Text="{TemplateBinding Content}" Foreground="{StaticResource HighlightedTextBrush}"
                           Background="Transparent"
                           FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="MainDataGridRow" TargetType="{x:Type DataGridRow}">
    <Setter Property="Background" Value="{StaticResource LightBackgroundBrush}" />
    <Setter Property="BorderBrush" Value="{StaticResource Faded10MidBackgroundBrush}"/>
    <Setter Property="BorderThickness" Value="0,0,0,1" />
    <Setter Property="SnapsToDevicePixels" Value="true" />
    <Setter Property="Padding" Value="5"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridRow}">
                <Border x:Name="DGR_Border"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Background="{TemplateBinding Background}"
                        SnapsToDevicePixels="True"
                        CornerRadius="0"
                        Margin="0,5"
                        Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}">
                    <SelectiveScrollingGrid>
                        <SelectiveScrollingGrid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                        </SelectiveScrollingGrid.ColumnDefinitions>
                        <SelectiveScrollingGrid.RowDefinitions>
                            <RowDefinition Height="*" />
                            <RowDefinition Height="Auto" />
                        </SelectiveScrollingGrid.RowDefinitions>
                        <DataGridCellsPresenter Grid.Column="1"
                                            ItemsPanel="{TemplateBinding ItemsPanel}"
                                            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        <DataGridDetailsPresenter Grid.Column="1"
                                              Grid.Row="1"
                                              SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                                              Visibility="{TemplateBinding DetailsVisibility}" />
                        <DataGridRowHeader Grid.RowSpan="2"
                                       SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                                       Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                    </SelectiveScrollingGrid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="MainDataGridCell" TargetType="{x:Type DataGridCell}">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                    <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
        </Trigger>
    </Style.Triggers>
</Style>

列标题、行和单元格样式的 xaml

<DataGrid.Columns>
            <DataGridTemplateColumn x:Name="dateColumn" Header="Race Time" MinWidth="110" Width="Auto" CellTemplate="{StaticResource RacesRaceTimeTemplate}" />
            <DataGridTemplateColumn x:Name="iconColumn"  Width="62" CellTemplate="{StaticResource RacesRaceIconTemplate}"/>
            <DataGridTemplateColumn x:Name="nameColumn" Width="*" CellTemplate="{StaticResource RacesRaceDescriptionTemplate}"/>
            <DataGridTemplateColumn x:Name="favsColumn" Width="auto" Header="Fav / 2nd Fav" CellTemplate="{StaticResource RacesFavSelectionsTemplate}" />
            <DataGridTemplateColumn x:Name="additionalColumn" Width="78" CellTemplate="{StaticResource RacesAdditionalOptionsTemplate}" />
        </DataGrid.Columns>

目前我可以通过为列设置硬编码宽度来解决这个问题,但这不是一个合理的解决方案,因为我们将拥有可变宽度的内容。

有人有解决这个问题的办法吗?

【问题讨论】:

  • 你看到这个答案了吗link
  • 我已经有一段时间没有使用 xaml 了。这个问题是特定于设备的吗?
  • 我看到你在第一列指定Width="Auto",在第三列指定Width="*"。我理解*的意思是成比例
  • 这是一个有用的 SO 问题:stackoverflow.com/questions/1768293/… .. 可能是 Auto, "62", 5*, 3.75*, 1.25* 在附加列上的最小值为“78”.. 应该是最后 3 列分配了剩余列的 100%列大小。
  • 你有没有想过使用Dispatcher来同步数据和UI?

标签: c# wpf xaml wpfdatagrid


【解决方案1】:

你有没有尝试设置所有列的最小宽度,然后根据百分比指定宽度

<DataGrid.Columns>
        <DataGridTemplateColumn x:Name="dateColumn" MinWidth="110" Width="*" Header="Race Time" CellTemplate="{StaticResource RacesRaceTimeTemplate}" />
        <DataGridTemplateColumn x:Name="iconColumn"  MinWidth="62" Width="2*" CellTemplate="{StaticResource RacesRaceIconTemplate}"/>
        <DataGridTemplateColumn x:Name="nameColumn" MinWidth="500" Width="3*" CellTemplate="{StaticResource RacesRaceDescriptionTemplate}"/>
        <DataGridTemplateColumn x:Name="favsColumn" MinWidth="232" Width="3*" Header="Fav / 2nd Fav" CellTemplate="{StaticResource RacesFavSelectionsTemplate}" />
        <DataGridTemplateColumn x:Name="additionalColumn" MinWidth="78" Width="*" CellTemplate="{StaticResource RacesAdditionalOptionsTemplate}" />
</DataGrid.Columns>

【讨论】:

    【解决方案2】:

    你可能会看到这个answer

    在设置 ItemsSource 后尝试以编程方式更新宽度列

    foreach (DataGridColumn c in dg.Columns)
        c.Width = 0;
    
    // Update your DG's source here
    
    foreach (DataGridColumn c in dg.Columns)
        c.Width = DataGridLength.Auto; 
    

    然后 UpdateLayout 你的 DataGrid。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-12
      • 1970-01-01
      • 1970-01-01
      • 2011-08-26
      • 1970-01-01
      • 1970-01-01
      • 2012-02-07
      • 2010-09-27
      相关资源
      最近更新 更多