WPF Datagrid : On load, selection on current item (highlighting)

14,478

Solution 1

When using a Model as the DataContext for a WPF Window, the DataGrid's SelectionChanged event doesn't get called until after the Window is loaded which is why the row is never highlighted and you only see the first row with the partial highlight. There may be a more elegant way, but here's a work-around.

In the Window's loaded event or the DataGrid's loaded event, reset the SelectedItem binding:

public MainWindow()
{
    InitializeComponent(); 
    this.Loaded += new RoutedEventHandler( OnLoaded );
}

// could also be placed in the DataGrid's loaded event handler
private void OnLoaded( object sender, RoutedEventArgs e )
{
    if( dataGrid != null && Model.SelectedItem != null )
    {
        var selected = Model.SelectedItem;
        Model.SelectedItem = null;
        Model.SelectedItem = selected;
    }
}

Here's a complete working sample.

XAML

<Window x:Class="WpfDataGridHighlightOnLoad.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:model="clr-namespace:WpfDataGridHighlightOnLoad" 
        Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>
        <model:MainWindowModel x:Name="Model" />
    </Window.DataContext>

    <Grid>
        <DataGrid AutoGenerateColumns="True" SelectionMode="Single"
                  HorizontalAlignment="Stretch" 
                  Name="dataGrid" 
                  VerticalAlignment="Top"
                  ItemsSource="{Binding ItemList}"
                  SelectedItem="{Binding SelectedItem}">
        </DataGrid>

        <Button Content="Cycle Selection" Click="OnCycleClick" 
                Height="23" 
                HorizontalAlignment="Right" 
                Name="button1" 
                VerticalAlignment="Bottom" Width="125" />

        <Button Content="Reset Grid" Click="OnResetClick" 
                Height="23" 
                HorizontalAlignment="Left" 
                Name="button2" 
                VerticalAlignment="Bottom" Width="125" />

    </Grid>
</Window>

Code Behind

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;

namespace WpfDataGridHighlightOnLoad
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();   
            this.Loaded += new RoutedEventHandler( OnLoaded );
        }

        // could also be placed in the DataGrid's loaded event handler
        private void OnLoaded( object sender, RoutedEventArgs e )
        {
            if( dataGrid != null && Model.SelectedItem != null )
            {
                var selected = Model.SelectedItem;
                Model.SelectedItem = null;
                Model.SelectedItem = selected;
            }
        }

        private void OnCycleClick( object sender, RoutedEventArgs e )
        {
            int index = Model.ItemList.IndexOf( Model.SelectedItem );
            index = index == Model.ItemList.Count - 1 ? 0 : index + 1;
            Model.SelectedItem = Model.ItemList[index];
        }

        private void OnResetClick( object sender, RoutedEventArgs e )
        {
            Model.Reset();
        }
    }

    public class MainWindowModel : INotifyPropertyChanged
    {
        public MainWindowModel()
        {
            Reset();
        }

        public void Reset()
        {
            ItemList = new List<Person>
                           {
                               new Person("Joe", 20),
                               new Person("John", 30),
                               new Person("Jane", 40),
                               new Person("Jill", 50),
                               new Person("Fido", 7),
                           };

            SelectedItem = ItemList[2];
        }

        private Person _selectedItem;
        public Person SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                _selectedItem = value;
                NotifyPropertyChanged( "SelectedItem" );
            }
        }

        private List<Person> _itemList;
        public List<Person> ItemList
        {
            get { return _itemList; }
            set
            {
                _itemList = value;
                NotifyPropertyChanged( "ItemList" );
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged( String info )
        {
            if( PropertyChanged != null )
            {
                PropertyChanged( this, new PropertyChangedEventArgs( info ) );
            }
        }

        #endregion
    }

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public Person( string name, int age )
        {
            Name = name;
            Age = age;
        }

        public override string ToString()
        {
            return Name;
        }
    }
}

Solution 2

I had the same "problem" and finally found a pretty good solution to the problem. As you already said is not that the row isn't selected but that it does not highlight the row. If you watch carefully you will notice that when you click anywhere in the row (using the mouse) it still doesn't highlight the row, only the cells inside it.

So 2 options;

  • Create code to select the cells of the row
  • or create a Style.Trigger to highlight the row (which is the best option in my mind).

To do this, add something like this to the datagrid in the xaml-file:

            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow">
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Background" Value="DodgerBlue"/>
                            <Setter Property="Foreground" Value="White"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.RowStyle>

Hope it helps!

Cheers, LTB

Share:
14,478
Philippe Lavoie
Author by

Philippe Lavoie

Grizzly dans Sharegate Dev.

Updated on June 09, 2022

Comments

  • Philippe Lavoie
    Philippe Lavoie almost 2 years

    I have a WPF Datagrid binded to some properties in my ViewModel

    <DataGrid AutoGenerateColumns="False" Name="dataGrid" SelectionMode="Single"
              ItemsSource="{Binding ItemList}" SelectedItem="{Binding SelectedItem}">
    ...
    </DataGrid>
    

    When my window load and the Datagrid too, I set the SelectedItem and it binds fine but the row isn't highlighted. The moment I click a row, the row highlight and the problem is resolved.

    How can I set/trigger the highlighting of the SelectedItem in the DataGrid on load/initialization ?

    EDIT:

    It's actually selected because I have the little selection cell. It's just the rendering of the Highlighting that does not trigger.

    enter image description here

  • Philippe Lavoie
    Philippe Lavoie about 13 years
    There is no Loaded event on UIElement
  • Metro Smurf
    Metro Smurf about 13 years
    DataGrid inherits from Controls which does have a Loaded event: MSDN DataGrid Events
  • GilShalit
    GilShalit over 12 years
    @Smurf - resetting SelecteItem has solved an issue i have been trying to understand for a couple of days. Thanks!!!
  • user1841243
    user1841243 over 10 years
    this works the first time on loading. but when I change the viewmodel value, it still doesn't highlight the correct row. allthough it is selected.