Align DataGrid Column Header to Center - c#

I need to align WPF DataGrid Column Header text to Center. I created a style and attached that using the HeaderStyle property as below.
Style
<Window.Resources>
<Style x:Key="CenterGridHeaderStyle" TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</Window.Resources>
Column
<DataGridTextColumn
Binding="{Binding Path=Name}" Header="Name" IsReadOnly="True"
HeaderStyle="{DynamicResource CenterGridHeaderStyle}"/>
But this does not align Column Header text to the Center. How can I do this?

Check this
<DataGridTextColumn Header="Nombre"
Binding="{Binding Nombre}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment"
Value="Center" />
</Style>
</DataGridTextColumn.HeaderStyle>

It should be StaticResource instead of DynamicResource in the Column:
Style
<Window.Resources>
<Style x:Key="CenterGridHeaderStyle" TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</Window.Resources>
Column
<DataGridTextColumn
Binding="{Binding Path=Name}" Header="Name" IsReadOnly="True"
HeaderStyle="{StaticResource CenterGridHeaderStyle}"/>

There is a response for doing it programmatically at AutoGeneratingColumn:
private void dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
e.Column.HeaderStyle = new Style(typeof(DataGridColumnHeader));
e.Column.HeaderStyle.Setters.Add(new Setter(HorizontalContentAlignmentProperty, HorizontalAlignment.Center));
}
Tip, use attributes:
public class ColumnNameAttribute : Attribute
{
public HorizontalAlignment Alignment { get; set;}
public ColumnNameAttribute(HorizontalAlignment alignment){
Alignment = alignment;
}
public class Example(){
[ColumnName(HorizontalAlignment.Center)]
public string Column {get; set;}
}
private void dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
var desc = e.PropertyDescriptor as PropertyDescriptor;
var att = desc.Attributes[typeof(ColumnNameAttribute)] as ColumnNameAttribute;
if(att != null){
e.Column.HeaderStyle = new Style(typeof(DataGridColumnHeader));
e.Column.HeaderStyle.Setters.Add(new Setter(HorizontalContentAlignmentProperty, att.Alignment));
}
}

Try this
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</DataGridTextColumn.CellStyle>

I landed here while searching for the same problem for Row Headers alignment. In case anyone else was searching, the solution is as simple as:
<DataGrid.RowHeaderStyle>
<Style TargetType="DataGridRowHeader">
<Style.Resources>
<Style TargetType="StackPanel">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</Style.Resources>
</Style>
</DataGrid.RowHeaderStyle>

Here is what I am using to change the header text alignment.
<DataGrid.Columns>
<DataGridTemplateColumn Width="Auto" MinWidth="60" Header=" ID " IsReadOnly="True"> <DataGridTemplateColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Background" Value="#c0c0c0"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontSize" Value="12"/>
</Style> </DataGridTemplateColumn.HeaderStyle> <DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding ID}" TextAlignment="Center" />
</DataTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Related

DataGrid RowStyle not working for IsSelected and IsMouseOver combination

I have a simple DatGrid. I want to set the background color of my rows accordingly to specific criteria. In this example the row is just red at the beginning.
I want to change that basic background color to different colors
when the mouse hovers over the row
when the row is selected
when the row is selected and the mouse hovers over it
The thing is that it works for the cells but not for the complete row.
I set a MultiTrigger for the last requirement and it changes the cell color but not the color of the complete row. When I move the CellStyle MultiTrigger to RowStyle it does not do anything anymore.
<Window x:Class="MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTest" >
<Window.DataContext>
<local:MyWindowViewModel />
</Window.DataContext>
<Grid>
<DataGrid ItemsSource="{Binding Items}"
AutoGenerateColumns="False"
SelectionMode="Single" SelectionUnit="FullRow" >
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="Red"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Green" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Orange" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True" />
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="Yellow"/>
</MultiTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="FirstName" Width="50*" Binding="{Binding FirstName}" />
<DataGridTextColumn Header="LastName" Width="50*" Binding="{Binding LastName}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Model / ViewModel:
class Model
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
class MyWindowViewModel
{
public List<Model> Items { get; private set; }
public MyWindowViewModel()
{
Items = new List<Model>();
Items.Add(new Model { FirstName = "AB", LastName = "CD"});
Items.Add(new Model { FirstName = "EF", LastName = "GH" });
Items.Add(new Model { FirstName = "IJ", LastName = "KL" });
}
}
You need a DataTrigger on your DataGridCell style that will bind to parent rows IsSelected so all cells change the style rather than just the one you are hovering.
<DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" Value="True">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>

wrong show text when selected item datagrid wpf

i use this code
txt_f1.Text = datagrid_customer.SelectedCells[1].Column.GetCellContent(datagrid_customer.SelectedItem).ToString();
but when i click any item
show me:
System.windows.controls.textblock
datagrid code
<DataGrid HorizontalAlignment="Left" Height="100" Margin="861,-30,-261,0"
VerticalAlignment="Top" Width="100" Name="datagrid_customer"
SelectionChanged="datagrid_customer_SelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Header="کد محصول" Binding="{Binding MahID}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="FontFamily" Value="B Yekan" />
<Setter Property="FontSize" Value="12" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
If you need to get MahID, you should be able to get it from the SelectedItem itself. Like,
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var grid = sender as DataGrid;
var mahId = (grid.SelectedItem as YourModel).MahID;
}

EditingElementStyle in a DataGridTextColumn

I need to be able to distinguish from which column in a DataGrid, a TextBox has been edited:
<DataGridTextColumn Header="No" Binding="{Binding NumberOfItems}">
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="{x:Type TextBox}" x:Name="NumOfItems">
<Setter Property="MaxLength" Value="2"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Role" Binding="{Binding Role}" Width="0.75*">
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="{x:Type TextBox}" x:Name="Role">
<Setter Property="MaxLength" Value="30"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
so that I can update a database with the correct information. I have tried to use x:Name but, with the code below, the name is always empty
private void dgItems_CellEditEnding(object sender,
DataGridCellEditEndingEventArgs e)
{
if(e.EditingElement is TextBox)
{
TextBox t = e.EditingElement as TextBox;
..........
if (t.Name == "Role")
//do this
else if (t.NumOfItems)
//do this
}
Thanks for any help
You could set the Tag property in the Style:
<Style TargetType="{x:Type TextBox}">
<Setter Property="MaxLength" Value="30"/>
<Setter Property="Tag" Value="Role"/>
</Style>
if (t.Tag?.ToString() == "Role")

WPF create combo box programmatically

I'm trying to create DatagridComboBoxColumn from code behind. How can I link it to ElementStyle and EditingElementStyle?
I'm trying to create this:
<DataGridComboBoxColumn Width="*" ElementStyle="{StaticResource ComboBoxElementStyle}" EditingElementStyle="{StaticResource ComboBoxEditingElementStyle}" />
which creates this:
from this:
private DataGridComboBoxColumn CreateComboValueColumn()
{
DataGridComboBoxColumn column = new DataGridComboBoxColumn();
column.ElementStyle = ???;
column.EditingElementStyle = ???;
return column;
}
Which do not display comboBox:
Style which I'm trying to link:
<!-- ComboBox element and editing style -->
<Style x:Key="ComboBoxElementStyle" TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding ComboItems}"/>
<Setter Property="SelectedValue" Value="{Binding Value}" />
<Setter Property="DisplayMemberPath" Value="Text"/>
<Setter Property="SelectedValuePath" Value="ID" />
</Style>
<Style x:Key="ComboBoxEditingElementStyle" TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding ComboItems}"/>
<Setter Property="SelectedValue" Value="{Binding Value}" />
<Setter Property="DisplayMemberPath" Value="Text"/>
<Setter Property="SelectedValuePath" Value="ID" />
</Style>
Hello try something like this:
private DataGridComboBoxColumn CreateComboValueColumn()
{
DataGridComboBoxColumn column = new DataGridComboBoxColumn();
column.ElementStyle = YourWindowName.FindResource("ComboBoxElementStyle") as Style;
column.EditingElementStyle = YourWindowName.FindResource("ComboBoxEditingElementStyle") as Style;
return column;
}
Try something like(Style)FindResource("StyleOne")
Have a look here:
https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/resources-and-code

How to paint a line on a datagrid

How to paint a line on a datagrid, I'm trying like this but is not working.
the "row" variable is always null Falor...
private void PersonData()
{
foreach (SingleEstoqueEntrada item in DataGridEstoque.ItemsSource)
{
try
{
var row = DataGridEstoque.ItemContainerGenerator.ContainerFromIndex(I) as DataGridRow;
if (item.ESTOQUE == 0.00m)
row.Background = Brushes.Pink;
else
row.Background = Brushes.YellowGreen;
}
catch (Exception _Exception)
{
MessageBox.Show(_Exception.Message);
}
}
}
if the data is properly binded and there is a property ESTOQUE as mentioned (also assumed from the code), placing this style in the resources may perhaps give the desired effect
<Style TargetType="DataGridRow">
<Setter Property="Background"
Value="YellowGreen" />
<Style.Triggers>
<DataTrigger Binding="{Binding ESTOQUE}"
Value="0">
<Setter Property="Background"
Value="Pink" />
</DataTrigger>
</Style.Triggers>
</Style>
sample xaml
<DataGrid>
<DataGrid.Resources>
<Style TargetType="DataGridRow">
<Setter Property="Background"
Value="YellowGreen" />
<Style.Triggers>
<DataTrigger Binding="{Binding}"
Value="item 1">
<Setter Property="Background"
Value="Pink" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding}"
Header="A Column" />
<DataGridTextColumn Binding="{Binding Length}"
Header="Length" />
</DataGrid.Columns>
<sys:String>item 1</sys:String>
<sys:String>item 2</sys:String>
<sys:String>item 1</sys:String>
<sys:String>item 2</sys:String>
<sys:String>item 2</sys:String>
<sys:String>item 2</sys:String>
</DataGrid>
result
in above example I wrote trigger to modify all rows which have item 1
try
var row = DataGridEstoque.ItemContainerGenerator.ContainerFromItem(item)as DataGridRow;
instead of
var row = DataGridEstoque.ItemContainerGenerator.ContainerFromIndex(I) as DataGridRow;

Categories

Resources