I have a regular DataGrid from WPF 4.0 RTM, where I put data from a database. In order to make clean & light style of DataGrid I use a tall/high rows and by default DataGrid aligns row content in top vertical position, but I want to set a center vertical alignment.
I already tried to use this property
VerticalAlignment="Center"
in DataGrid options, but it doesn't help me.
Here is an example of XAML-code, describing my DataGrid without center vertical alignment:
<DataGrid x:Name="ContentDataGrid"
Style="{StaticResource ContentDataGrid}"
ItemsSource="{Binding}"
RowEditEnding="ContentDataGrid_RowEditEnding">
<DataGrid.Columns>
<DataGridTextColumn Header="UserID"
Width="100"
IsReadOnly="True"
Binding="{Binding Path=userID}" />
<DataGridTextColumn Header="UserName"
Width="100"
Binding="{Binding Path=userName}" />
<DataGridTextColumn Header="UserAccessLevel"
Width="100"
Binding="{Binding Path=userAccessLevel}" />
<DataGridTextColumn Header="UserPassword"
Width="*"
Binding="{Binding Path=userPassword}" />
</DataGrid.Columns>
</DataGrid>
Result of executing this code:
As you can see all row content has top vertical align.
What do I have to add in order to get center vertical alignment of each row content?
Complete solution of this issue at MSDN: Vertical alignment of DataGrid row content.
In brief, in style-file set:
<!--body content datagrid cell vertical centering-->
<Style x:Key="Body_Content_DataGrid_Centering"
TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In window file:
<DataGrid x:Name="ContentDataGrid"
Style="{StaticResource ContentDataGrid}"
CellStyle="{StaticResource Body_Content_DataGrid_Centering}"
ItemsSource="{Binding}"
RowEditEnding="ContentDataGrid_RowEditEnding">
<DataGrid.Columns>
<DataGridTextColumn Header="UserID"
Width="100"
IsReadOnly="True"
Binding="{Binding Path=userID}" />
<DataGridTextColumn Header="UserName"
Width="100"
Binding="{Binding Path=userName}" />
<DataGridTextColumn Header="UserAccessLevel"
Width="100"
Binding="{Binding Path=userAccessLevel}" />
<DataGridTextColumn Header="UserPassword"
Width="*"
Binding="{Binding Path=userPassword}" />
</DataGrid.Columns>
</DataGrid>
This will give you a wanted result:
To set individual text alignments you can use:
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Center" />
</Style>
</DataGridTextColumn.ElementStyle>
The following code will vertically align the content of a DataGridTextColumn cell:
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"></Setter>
</Style>
</DataGridTextColumn.ElementStyle>
Edit: I've come back to this problem and found the solution below to work better, it will center the contents of all the cells in DataGridTextRows both horizontally and vertically.
<UserControl.Resources>
<ResourceDictionary>
<Style TargetType="DataGridCell">
<Setter Property="HorizontalAlignment" Value="Stretch"></Setter>
<Setter Property="VerticalAlignment" Value="Stretch"></Setter>
<Setter Property="VerticalContentAlignment" Value="Stretch"></Setter>
<Setter Property="TextBlock.TextAlignment" Value="Center"></Setter>
<Setter Property="TextBlock.VerticalAlignment" Value="Center"></Setter>
</Style>
</ResourceDictionary>
</UserControl.Resources>
This one works for me
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.CellStyle>
You could also do without overriding the ControlTemplate:
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
The attribute value VerticalAlignment="Center" will center the DataGrid within its parent element.
You probably want VerticalContentAlignment.
Just if someone might need it as i did..
To only affect a single column you could use the 'ElementStyle' Property:
<DataGrid ItemsSource="{Binding}">
<DataGrid.Resources>
<Style x:Key="DataGridVerticalText" TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Header Title" Binding="{Binding}" ElementStyle="{StaticResource DataGridVerticalText}" />
</DataGrid.Columns>
</DataGrid>
Building on Jamier's answer, the following code did the trick for me when using auto-generated columns:
Style VerticalCenterStyle = new Style();
public MainWindow()
{
// This call is required by the designer.
InitializeComponent();
VerticalCenterStyle.Setters.Add(new Setter(VerticalAlignmentProperty, VerticalAlignment.Center));
}
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.Column is DataGridTextColumn) {
((DataGridTextColumn)e.Column).ElementStyle = VerticalCenterStyle;
}
}
This is my simple solution and it just works perfectly
<DataGridTemplateColumn Header="Hello" Width="200">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="World!" TextAlignment="Center" VerticalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I set the width to 200 so you can notice the difference.
Related
I'm trying to set the height of the rows in the datagrid dynamically , I mean the height of the datagrid should be based on the data binding ( from the database ) , I don't have a problem with columns , they are responsive when I maximize the window the columns increase and take the available space.
The problem now is with rows so what I need exactly is when I maximize the Window , the datagrid should take the available space vertically ( increase the font size of the headers and the data shown in the datagrid).
Is there any possibility to make the rows of the datagrid responsive ?
Xaml Code:
<DockPanel Grid.Row="2" Width="auto" MinWidth="800" Height="auto" >
<ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Auto">
<DataGrid VerticalScrollBarVisibility="Auto" Margin="20" Height="auto" Width="auto" GridLinesVisibility="All" ItemsSource="{Binding GridModel}" x:Name="UserGrid" MinWidth="1200"
VerticalAlignment="Top" FlowDirection="RightToLeft"
AutoGenerateColumns="False" CanUserAddRows="false" MinHeight="800"
Grid.RowSpan="2" RenderTransformOrigin="0.497,0.551" MouseDoubleClick="UserGrid_MouseDoubleClick" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Hidden">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Height" Value="Auto"/>
</Style>
</DataGrid.RowStyle>
<DataGrid.Resources>
<Style x:Key="DisableSelection" TargetType="DataGridCell">
<!-- <Setter Property="Focusable" Value="False"/> -->
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderBrush" Value="Transparent"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridCheckBoxColumn Header="choose" x:Name="choose" Binding="{Binding isChecked}" >
<DataGridCheckBoxColumn.CellStyle>
<Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="IsEditing" Value="True"/>
</Trigger>
</Style.Triggers>
<EventSetter Event="CheckBox.Checked" Handler="OnChecked"/>
<EventSetter Event="CheckBox.Unchecked" Handler="OnChecked"/>
<Setter Property="Background" Value="Transparent" />
</Style>
</DataGridCheckBoxColumn.CellStyle>
</DataGridCheckBoxColumn>
<DataGridTextColumn Width="*" CellStyle="{StaticResource DisableSelection}" Header="IDw" x:Name="workIdcl" Binding="{Binding wId}" IsReadOnly="True" />
<DataGridTextColumn Width="*" CellStyle="{StaticResource DisableSelection}" Header="subName" x:Name="subscriberNamecl" Binding="{Binding subName}" IsReadOnly="True"/>
<DataGridTextColumn Width="*" CellStyle="{StaticResource DisableSelection}" Header="UserName" x:Name="patientNamecl" Binding="{Binding UserName}" IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
</DockPanel>
I have a DataGridTextColumn in which I wrap text in one column.Since only one cell has more than numbers and for this case cable names it' displaying fine in 3 lines, but while in edit mode the wrapping goes away and I don't see the whole text. Using the arrow keys is needed. I'd like to have an editable and textwrapping texblock while in edit mode. Looked for some advice on SO but no success.
Any help?
CableEditorWindow.xaml:
<Controls:MetroWindow x:Class="GPZmodel.Windows.CableEditorWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="Edytor właściwości kabla" Height="664" Width="610"
Background="WhiteSmoke" WindowStartupLocation="CenterScreen">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto" MinHeight="70"/>
</Grid.RowDefinitions>
<DataGrid x:Name="CableEditDataGrid"
Style="{StaticResource AzureDataGrid}"
Grid.Row="0"
VerticalAlignment="Stretch"
ItemsSource="{Binding Rows, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
CanUserAddRows="False"
CanUserDeleteRows="False" CanUserSortColumns="True" AutoGenerateColumns="False"
ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto"
SelectionMode="Single">
<DataGrid.Columns>
<DataGridTextColumn Header="Pole" Width="Auto"
HeaderStyle="{StaticResource WysrodkujHeader}"
Binding="{Binding nazwa_pola,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
IsReadOnly="True"
>
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="Text" Value="ID">
<Setter Property="Background" Value="#FF84BCCD"/>
<Setter Property="FontSize" Value="13"/>
</Trigger>
</Style.Triggers>
<Setter Property="TextAlignment" Value="Center"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<!--THIS-->
<DataGridTextColumn Header="Wartość"
HeaderStyle="{StaticResource WysrodkujHeader}"
Width="*"
Binding="{Binding wartosc_pola, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
>
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ReadOnly}" Value="True">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Focusable" Value="False"/>
</DataTrigger>
</Style.Triggers>
<Style.Setters>
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style.Setters>
</Style>
</DataGridTextColumn.CellStyle>
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextBlock.TextWrapping" Value="Wrap"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<!--/THIS-->
<DataGridTextColumn x:Name="JednostkaTextBox"
Header="Jednostka"
HeaderStyle="{StaticResource WysrodkujHeader}"
Binding="{Binding jednostka_pola,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
IsReadOnly="True"
Width="0.4*">
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<Grid Grid.Row="1" Background="#4A6A95">
<Button Style="{StaticResource MainButtonStyle}" Content="Nadpisz" x:Name="NadpiszButton" HorizontalAlignment="Right" Width="120" Panel.ZIndex="1" Margin="0,0,10,21" Height="32" VerticalAlignment="Bottom" Click="NadpiszButton_Click" />
<Button Style="{StaticResource MainButtonStyle}" Content="Anuluj" Name="AnulujButton" Height="32" VerticalAlignment="Bottom" Panel.ZIndex="1" Margin="0,0,135,21" HorizontalAlignment="Right" Width="120" Click="AnulujButton_Click" />
</Grid>
</Grid>
Besides the ElementStyle for the TextBlock, you should also define an EditingElementStyle that sets the TextWrapping property for the TextBox to Wrap:
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="TextBox">
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
There is no TextBlock displayed while you're in edit mode. It's a TextBox.
Luckily, solution is simple:
add EditingElementStyle to your column, you can (or should) customize edit style separately
<DataGridTextColumn.EditingElementStyle>
<Style>
<Setter Property="TextBlock.TextWrapping" Value="Wrap"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
Your final code portion will look like this
<!-- THIS -->
<DataGridTextColumn Width="*"
Binding="{Binding wartosc_pola, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Header="Wartość"
HeaderStyle="{StaticResource WysrodkujHeader}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ReadOnly}" Value="True">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Focusable" Value="False" />
</DataTrigger>
</Style.Triggers>
<Style.Setters>
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
</Style.Setters>
</Style>
</DataGridTextColumn.CellStyle>
<DataGridTextColumn.ElementStyle>
<Style>
<Setter Property="TextBlock.TextWrapping" Value="Wrap" />
</Style>
</DataGridTextColumn.ElementStyle>
<DataGridTextColumn.EditingElementStyle>
<Style>
<Setter Property="TextBlock.TextWrapping" Value="Wrap" />
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
<!-- /THIS -->
I am trying to figure out how to force my column header to display an ellipse and/or scroll bar when the column shrinks. I know that the data inside of the textblock (column) can shrink to an ellipse but I can't figure out how to make the header do the same. I am defining my data grid in the following way (this is an example of the text columns):
<DataGrid Height="150" HorizontalAlignment="Stretch" VerticalScrollBarVisibility="Auto">
<DataGrid.Columns>
<DataGridTextColumn Header="Dataset Description" Width="370">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="ToolTip" Value="Name of database"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
In this example, I'd like to see something like "Dataset ..." or "Dataset" with an accompanying scroll bar when the user shrinks the "Dataset Description" column.
I tried adding something like this inside of the DataGridTextColumn but it doesn't produce any result/response:
<DataGridTextColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Visible"/>
</Style>
</DataGridTextColumn.HeaderStyle>
I suppose I could implement a listener to see when the columns are resized and to re-set the header values but I'd obviously like to avoid that. Any ideas are welcome!
You could do something like the following, implementing a DataGrid.ColumnHeaderStyle.
<DataGrid Height="150" HorizontalAlignment="Stretch" VerticalScrollBarVisibility="Auto">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock TextTrimming="CharacterEllipsis" Text="{Binding}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="Dataset Description" Width="370">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="ToolTip" Value="Name of database"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
I've this DataGrid structure:
<DataGrid AutoGenerateColumns="False"
CanUserAddRows="False"
HorizontalContentAlignment="Center"
CanUserResizeColumns="False"
CanUserSortColumns="False"
CanUserResizeRows="False"
BorderBrush="DimGray"
BorderThickness="1"
IsReadOnly="True"
ItemsSource="{Binding MatchStats}"
HorizontalAlignment="Right"
Width="255"
Margin="10, 10, 30, 0">
<DataGrid.Columns>
<DataGridTextColumn Header="Foo" Binding="{Binding Path = PlayingMatch}" >
<DataGridTextColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource MetroDataGridColumnHeader}">
<Setter Property="Background" Value="LightGreen" />
<Setter Property="Width" Value="85" />
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
...
what I need to do is set the DataGrid text of the row to center. I actually managed this situation in the header, but I'm not able to do this for the rows. I saw other similar questions on stack, but all of these use the textblock, and I doesn't use any textblock how you can see in the image.
Is possible do this?
Actual result:
The three 0 should go to center.
Add following style in your windows.resources section
<Style x:Key="{x:Type DataGridCell}" TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The DataGridTextColumn is build with a TextBlock for the Text. So when NOT changed (like the code you provided) it will work with TextBlock.TextAlignment.
<Style TargetType="{x:TypeDataGridCell}">
<Style.Setters>
<Setter Property="TextBlock.TextAlignment" Value="Center" />
</Style.Setters>
</Style>
I just tried using the following XAML in my WPF application.
<DataGridTextColumn Header="Due" Binding="{Binding QTYDue, Mode=OneWay}">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="FrameworkElement.HorizontalAlignment" Value="Center" />
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
Unfortunately, the behavior is that the previous styling for the control in MahApps Metro is removed. How do I keep the existing style, but just modify this one aspect of it.
Try this:
Style:
<Style x:Key="DatagridCellStyle1"
TargetType="{x:Type DataGridCell}"
BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
XAML:
<DataGridTextColumn Header="DUE"
Binding="{Binding QTYDue}"
CellStyle="{StaticResource DatagridCellStyle1}" />
OR
<DataGridTemplateColumn Header="DUE">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DataGridCell Style="{StaticResource DatagridCellStyle1}">
<TextBlock Text="{Binding QTYDue}"></TextBlock>
</DataGridCell>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>