Search code examples
c#wpfxamlmvvmdatagrid

Change way of highlight selected rows in DataGrid with styled cells


I'm creating WPF App and I'm using DataGrid. The problem is after I styled DataGridCell to have margins and alignment in every cell, selection only highlights the background behind text, not all cells.

Something like this:

enter image description here

Code behind styling:

            <DataGrid.CellStyle>
                <Style TargetType="DataGridCell">
                    <Setter Property="HorizontalAlignment" Value="Left"/>
                    <Setter Property="VerticalAlignment" Value="Center"/>
                    <Setter Property="Margin" Value="8,0,8,0"/>
                </Style>
            </DataGrid.CellStyle>

How to prevent it? There is some way to do it?\

Edit: I reproduce it on clean project without problems, all code of example:

<Window x:Class="WpfApp1.MainWindow"
    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:WpfApp1"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <DataGrid Name="grid" Margin="10">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Width="0.2*" Binding="{Binding first_name}"/>
            <DataGridTextColumn Header="Last Name" Width="0.2*" Binding="{Binding last_name}"/>
            <DataGridTextColumn Header="E-mail" Width="0.2*" Binding="{Binding email}"/>
            <DataGridTextColumn Header="Phone number" Width="0.2*" Binding="{Binding phone}"/>
        </DataGrid.Columns>
        <DataGrid.CellStyle>
            <Style TargetType="DataGridCell">
                <Setter Property="HorizontalAlignment" Value="Left"/>
                <Setter Property="VerticalAlignment" Value="Center"/>
                <Setter Property="Margin" Value="8,0,8,0"/>
            </Style>
        </DataGrid.CellStyle>
    </DataGrid>
</Grid>

Class of that xaml:

using System.Windows;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Client client = new Client();
        public MainWindow()
        {
            InitializeComponent();

            client = new Client()
            {
                first_name = "John",
                last_name = "Connor",
                email = "[email protected]",
                phone = "123456789"
            };

            this.grid.DataContext = client;
            this.grid.Items.Add(client);
        }
    }

    public class Client
    {
        public string first_name { get; set; }
        public string last_name { get; set; }
        public string email { get; set; }
        public string phone { get; set; }
    }
}

Solution

  • It seems, that Margin makes problems. So try to get rid of Margin if you can. If not, I'm afraid you have to override the default control template to change the DataGrid's behavior and have a clean solution. As work around you could change a color of the selected row, but if the DataGrid lost focus it will be ugly again.

    <DataGrid.CellStyle>
        <Style TargetType="DataGridCell">
            <Setter Property="HorizontalContentAlignment" Value="Left"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Margin" Value="8,0,8,0"/>
        </Style>                
    </DataGrid.CellStyle>
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </DataGrid.RowStyle>
    

    I would also use HorizontalContentAlignment and VerticalContentAlignment instead of HorizontalAlignment and VerticalAlignment.

    E.g. you could also use DataGridTemplateColumn instead of DataGridTextColumn and put Margin to the control in DataTemplate:

    <DataGrid.Columns>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding first_name}" Margin="8,0,8,0"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>                    
        </DataGridTemplateColumn>
        <!--Other columns-->
    </DataGrid.Columns>