Search code examples
wpfdatagridinitializationselectionhighlighting

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


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


Solution

  • 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;
            }
        }
    }