Reputation: 81
My WPF 4.5 application has a small (but annoying) visual bug where a DataGrid
's cells are cut off upon loading:
Dropbox link to the screenshot
But once you resize the window (click the square button in the upper right corner) and re-maximize it, the DataGrid
's cells appear as they should:
Dropbox link to the screenshot
In the XAML, every column's width is set to Auto
, except for the "Name" column, which is *
. Is there anything I can do to prevent this visual bug from happening/is there anything I'm doing that's causing this bug?
Here's my XAML:
<DataGrid ItemsSource="{Binding Datasets, NotifyOnTargetUpdated=True}" Name="dsDatagrid" SelectionMode="Extended" MouseDoubleClick="ViewDataset">
<DataGrid.Style>
<Style BasedOn="{StaticResource {x:Type DataGrid}}" TargetType="DataGrid">
<Setter Property="Visibility" Value="Visible"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsWorking}" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Style>
<i:Interaction.Triggers>
<i:EventTrigger EventName="TargetUpdated">
<cmd:EventToCommand Command="{Binding CollectionChangedCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand Command="{Binding SelectionChangedCommand}" CommandParameter="{Binding ElementName=dsDatagrid, Path=SelectedItems}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.Columns>
<DataGridTemplateColumn Header="" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Name="NameCell" Background="Transparent" HorizontalAlignment="Left" VerticalAlignment="Center">
<Button Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=DataContext.BackupSingleCommand}" CommandParameter="{Binding}" Style="{StaticResource BackupSingleButtonStyle}" Margin="5 10"/>
<Button Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=DataContext.DeleteSingleCommand}" CommandParameter="{Binding}" Style="{StaticResource DeleteSingleButtonStyle}" Margin="5 10"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="ID" Width="Auto" Binding="{Binding Id}"/>
<DataGridTemplateColumn Header="Name" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" TextWrapping="Wrap"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Source Images" Width="Auto" Binding="{Binding SourceImages.Count, StringFormat={}{0:N0}, TargetNullValue=NONE}"/>
<DataGridTextColumn Header="Start Time" Width="Auto" Binding="{Binding StartTime, StringFormat={}{0:MM}/{0:dd}/{0:yy} {0:HH}\:{0:mm}\:{0:ss}}"/>
<DataGridTextColumn Header="End Time" Width="Auto" Binding="{Binding EndTime, StringFormat={}{0:MM}/{0:dd}/{0:yy} {0:HH}\:{0:mm}\:{0:ss}, TargetNullValue=In Progress}"/>
<DataGridTemplateColumn Header="Status" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Status}" TextWrapping="WrapWithOverflow"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
If it's relevant, here's my DataGrid
style:
<Style TargetType="DataGridColumnHeader">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="{StaticResource BannerNormalBrush}"/>
<Setter Property="Padding" Value="24 10"/>
</Style>
<Style TargetType="DataGridRow">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FontSize" Value="16"/>
</Style>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="24 0"/>
<Setter Property="Foreground" Value="{StaticResource TextBlockDisabledForegroundBrushDark}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Border Name="Border" Padding="{TemplateBinding Padding}" Background="Transparent">
<ContentPresenter VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource DataGridRowSelectedBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="DataGrid">
<Setter Property="GridLinesVisibility" Value="None"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="RowBackground" Value="{StaticResource DataGridOddRowBackgroundBrush}"/>
<Setter Property="AlternatingRowBackground" Value="{StaticResource DataGridEvenRowBackgroundBrush}"/>
<Setter Property="CanUserResizeRows" Value="False"/>
<Setter Property="CanUserResizeColumns" Value="False"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="SelectionMode" Value="Single"/>
<Setter Property="RowHeaderWidth" Value="0"/>
<Setter Property="CanUserReorderColumns" Value="False"/>
<Setter Property="CanUserSortColumns" Value="False"/>
<Setter Property="AutoGenerateColumns" Value="False"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="EnableRowVirtualization" Value="True"/>
<Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"/>
<Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling"/>
<Setter Property="Background" Value="Transparent"/>
</Style>
Upvotes: 2
Views: 2033
Reputation: 1186
This issue is explained there. In my case, and probably yours, the datagrid is binded to an ObservableCollection
that is updated later by code that looks like this :
Documents.Clear();
foreach (Document doc in documents)
{
Documents.Add(doc);
}
Sadly, the datagrid wont update the columns width then the ObservableCollection
content change so the width of the columns will stay the same (which would be the header width by default).
The link I provide give some solutions in the answers, in my case I did the following :
// Don't bind anymore in the XAML but pass data directly to the ItemsSource (which will trigger the update)
DataGridDocuments.ItemsSource = documents;
// Or call UpdateLayout then the data is updated
Documents.Clear();
foreach (Document doc in documents)
{
Documents.Add(doc);
}
DataGridDocuments.UpdateLayout();
Upvotes: 0
Reputation: 4978
Haven't really tried your code, but just by looking at it, I have a hunch...
StackPanels tend to have problems calculating their available space, so your problem may be caused by the StackPanel inside your column's DataTemplate, that is unable to communicate its size correctly to the column on load.
My suggestion is to change the StackPanel for another Panel. In this case, a good old Grid would work just fine, and I bet you won't see any glitch this time.
<DataGridTemplateColumn Header="" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid Name="NameCell" Background="Transparent" HorizontalAlignment="Left" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=DataContext.BackupSingleCommand}" CommandParameter="{Binding}" Style="{StaticResource BackupSingleButtonStyle}" Margin="5 10"/>
<Button Grid.Column="1" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=DataContext.DeleteSingleCommand}" CommandParameter="{Binding}" Style="{StaticResource DeleteSingleButtonStyle}" Margin="5 10"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Upvotes: 1