Reputation: 92
I have a weird behaviour in a datagrid control in WPF. Basically I add custom objects to a datagrid, which contains just one column. In this column I visualize an image and a textblock in a stackpanel. It works fine, until I define the width of the image. Then I get this.
Hope someone can help me. Thanks in advance!
Here is a code excerpt for the user control:
<Grid>
<DataGrid Margin="2"
CanUserResizeRows="False"
AutoGenerateColumns="False"
ItemsSource="{Binding dataGridRows}"
SelectionChanged="selectionChanged"
SelectionMode="Single"
Style="{DynamicResource PaletteDataGrid}"
ClipboardCopyMode="None"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserSortColumns="False"
GridLinesVisibility="None"
HeadersVisibility="None"
HorizontalAlignment="Stretch"
IsReadOnly="True"
BorderBrush="{x:Null}"
RowStyle="{DynamicResource PaletteRowStyle}"
CellStyle="{DynamicResource PaletteDataGridCell}">
<DataGrid.Resources>
<Style TargetType="ScrollBar"
BasedOn="{StaticResource ScrollBar}" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding itemImage}"
MaxHeight="20"
MaxWidth="20" />
<TextBlock Text="{Binding itemName}"
VerticalAlignment="Center"
Width="Auto"
Margin="5, 0, 0, 0" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
The styling template of the datagrid:
<Style x:Key="PaletteDataGrid"
TargetType="{x:Type DataGrid}">
<Setter Property="Background"
Value="{StaticResource TabBackground}" />
<Setter Property="Foreground"
Value="{StaticResource TabItemActiveText}" />
<Setter Property="BorderBrush"
Value="Transparent" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="RowDetailsVisibilityMode"
Value="VisibleWhenSelected" />
<Setter Property="ScrollViewer.CanContentScroll"
Value="true" />
<Setter Property="ScrollViewer.PanningMode"
Value="VerticalOnly" />
<Setter Property="Stylus.IsFlicksEnabled"
Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGrid}">
<Border BorderBrush="Transparent"
BorderThickness="0,0,0,0"
Background="{StaticResource TabBackground}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="True">
<ScrollViewer x:Name="DG_ScrollViewer"
Focusable="false">
<ScrollViewer.Template>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button Command="{x:Static DataGrid.SelectAllCommand}"
Focusable="false"
Style="{DynamicResource {ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}}"
Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.All}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter"
Grid.Column="1"
Visibility="Hidden" />
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter"
CanContentScroll="{TemplateBinding CanContentScroll}"
Grid.Column="2"
Grid.Row="1" />
<ScrollBar x:Name="PART_VerticalScrollBar"
Grid.Column="0"
Maximum="{TemplateBinding ScrollableHeight}"
Orientation="Vertical"
Grid.Row="1"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
ViewportSize="{TemplateBinding ViewportHeight}">
</ScrollBar>
</Grid>
</ControlTemplate>
</ScrollViewer.Template>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsGrouping"
Value="true" />
<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping"
Value="false" />
</MultiTrigger.Conditions>
<Setter Property="ScrollViewer.CanContentScroll"
Value="false" />
</MultiTrigger>
</Style.Triggers>
</Style>
<Style x:Key="PaletteRowStyle"
TargetType="{x:Type DataGridRow}">
<Setter Property="Background"
Value="Transparent" />
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="Validation.ErrorTemplate"
Value="{x:Null}" />
<Setter Property="ValidationErrorTemplate">
<Setter.Value>
<ControlTemplate>
<TextBlock Foreground="Red"
Margin="2,0,0,0"
Text="!"
VerticalAlignment="Center" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRow}">
<Border x:Name="DGR_Border"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
CornerRadius="2"
SnapsToDevicePixels="True"
Padding="5,5,5,5">
<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.Triggers>
<Trigger Property="IsNewItem"
Value="True">
<Setter Property="Margin"
Value="{Binding NewItemMargin, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
</Trigger>
<Trigger Property="IsMouseOver"
Value="False">
<Setter Property="Background"
Value="{StaticResource TabBackground}" />
<Setter Property="BorderBrush"
Value="Transparent" />
<Setter Property="BorderThickness"
Value="1,1,1,1" />
</Trigger>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="{StaticResource ItemRolloverBackground}" />
<Setter Property="BorderBrush"
Value="{StaticResource TabItemActiveBorder}" />
<Setter Property="BorderThickness"
Value="1,1,1,1" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="PaletteDataGridCell"
TargetType="{x:Type DataGridCell}">
<Setter Property="Background"
Value="Transparent" />
<Setter Property="BorderBrush"
Value="Transparent" />
<Setter Property="BorderThickness"
Value="0" />
<Style.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Background"
Value="Transparent" />
<Setter Property="Foreground"
Value="{StaticResource TabItemActiveText}" />
<Setter Property="BorderBrush"
Value="Transparent" />
</Trigger>
<Trigger Property="Selector.IsSelectionActive"
Value="False">
<Setter Property="Background"
Value="Transparent" />
<Setter Property="Foreground"
Value="{StaticResource TabItemActiveText}" />
<Setter Property="BorderBrush"
Value="Transparent" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin"
Value="True">
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</Style.Triggers>
</Style>
ScrollBar Style:
<Style x:Key="ScrollBarLineButton"
TargetType="{x:Type RepeatButton}">
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Focusable"
Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border Name="Border"
Margin="1"
CornerRadius="2"
Background="{StaticResource TabItemActiveBorder}"
BorderBrush="{StaticResource TabItemActiveText}"
BorderThickness="1">
<Path HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="{StaticResource TabItemActiveText}"
Data="{Binding Path=Content,RelativeSource={RelativeSource TemplatedParent}}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed"
Value="true">
<Setter TargetName="Border"
Property="Background"
Value="{StaticResource TabItemActiveBorder}" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Foreground"
Value="{StaticResource DisabledForegroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarPageButton"
TargetType="{x:Type RepeatButton}">
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="IsTabStop"
Value="false" />
<Setter Property="Focusable"
Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border Background="Transparent" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarThumb"
TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="Margin"
Value="0,0,10,0" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="IsTabStop"
Value="false" />
<Setter Property="Focusable"
Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border CornerRadius="2"
Background="{StaticResource TabItemActiveBorder}"
BorderBrush="{StaticResource TabItemActiveBorder}"
BorderThickness="1" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="VerticalScrollBar"
TargetType="{x:Type ScrollBar}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.00001*" />
</Grid.RowDefinitions>
<Border Grid.RowSpan="1"
CornerRadius="2"
Background="{StaticResource TabBackground}"/>
<Track Name="PART_Track"
Grid.Row="1"
IsDirectionReversed="true">
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource ScrollBarPageButton}"
Command="ScrollBar.PageUpCommand" />
</Track.DecreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource ScrollBarThumb}"
Margin="1,0,1,0"
Background="{StaticResource TabItemInactiveBackground}"
BorderBrush="{StaticResource TabItemInactiveBackground}" />
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource ScrollBarPageButton}"
Command="ScrollBar.PageDownCommand" />
</Track.IncreaseRepeatButton>
</Track>
</Grid>
</ControlTemplate>
<Style x:Key="ScrollBar"
TargetType="{x:Type ScrollBar}">
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Style.Triggers>
<Trigger Property="Orientation"
Value="Vertical">
<Setter Property="Width"
Value="8" />
<Setter Property="Height"
Value="Auto" />
<Setter Property="Template"
Value="{StaticResource VerticalScrollBar}" />
</Trigger>
</Style.Triggers>
</Style>
UPDATE
I noticed that the effect goes away when I load items which overflow the current cell width. It seems that the cell defines its width according to the content (which is logical). But how can I define that the cell has a max width which doesn't exceed the datagrid boundaries and a min width which uses the whole datagrid width?
[Here][2] you see that the corner radius is only shown on the left side, not on the right because of the overflow.
UPDATE 2
The thing I want to achieve is this.
Additional information: The Datagrid is situated in a user control, which is bound to the content of a TabControl. Here is the code from the mainWindow.xaml:
<Grid Margin="0,96,0,0">
<TabControl ItemContainerStyle="{StaticResource TabItem}"
TabStripPlacement="Right"
ItemsSource="{Binding loadedPalettes}"
Style="{StaticResource TabControl}"
Height="Auto"
SelectionChanged="paletteSelectionChanged"
SelectedIndex="{Binding selPaletteIndex}"
Width="Auto"
Margin="0,5,0,0">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}">
<TextBlock.LayoutTransform>
<RotateTransform Angle="270" />
</TextBlock.LayoutTransform>
</TextBlock>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<my:tabDataGrid />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
Upvotes: 0
Views: 897
Reputation: 92
Ok, I solved the problem. It seems I messed up the row style template for the datagrid and forgot to give the DataGridTemplateColumn
of the datagrid a defined width:
ScrollViewer in the datagrid row style template:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRow}">
<Border x:Name="DGR_Border"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
CornerRadius="2"
SnapsToDevicePixels="True"
Padding="5,5,5,5">
<SelectiveScrollingGrid>
<SelectiveScrollingGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</SelectiveScrollingGrid.ColumnDefinitions>
<SelectiveScrollingGrid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</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>
Datagrid columns definition in userControl.xaml
<DataGrid.Columns>
<DataGridTemplateColumn Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding itemImage}"
Grid.Column="0"
MaxHeight="20"
MaxWidth="20" />
<TextBlock Text="{Binding itemName}"
Grid.Column="1"
Margin="5, 0, 0, 0" />
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Thanks for the answers!
Upvotes: 0
Reputation: 38199
Try to use Grid
instead of StackPanel
inside of DataTemplate
:
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding itemImage}" MaxHeight="20"
MaxWidth="20" />
<TextBlock Grid.Column="1" Text="{Binding itemName}"
VerticalAlignment="Center"
Width="Auto"
Margin="5, 0, 0, 0" />
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
Upvotes: 0