Search code examples
wpfmvvmdatagriddatatable

How to set selected item of a DataGrid programmatically in WPF with MVVM application?


I have bound the DataTable to the DataGrid control. How can I set the selected item programmatically ?

Example

In my view model I have a property of type DataTable to bind the DataGrid

 private DataTable sizeQuantityTable;

 public DataTable SizeQuantityTable
 {
        get
        {
            return sizeQuantityTable;
        }
        set
        {
            sizeQuantityTable = value;
            NotifyPropertyChanged("SizeQuantityTable");
        }
  }

My XAML

<DataGrid 
            ItemsSource="{Binding SizeQuantityTable}"
            AutoGenerateColumns="True" 
            Margin="0,0,0,120" />

The constructor of the view model (assigning dummy values)

this.SizeQuantityTable = new DataTable();

DataColumn sizeQuantityColumn = new DataColumn();
sizeQuantityColumn.ColumnName = "Size Quantity";
this.SizeQuantityTable.Columns.Add(sizeQuantityColumn);

DataColumn sColumn = new DataColumn();
sColumn.ColumnName = "S";
this.SizeQuantityTable.Columns.Add(sColumn);

DataColumn mColumn = new DataColumn();
mColumn.ColumnName = "M";
this.SizeQuantityTable.Columns.Add(mColumn);

DataRow row1 = this.SizeQuantityTable.NewRow();
row1[sizeQuantityColumn] = "Blue";
row1[sColumn] = "12";
row1[mColumn] = "15";
this.SizeQuantityTable.Rows.Add(row1);

DataRow row2 = this.SizeQuantityTable.NewRow();
row2[sizeQuantityColumn] = "Red";
row2[sColumn] = "18";
row2[mColumn] = "21";
this.SizeQuantityTable.Rows.Add(row2);

DataRow row3 = this.SizeQuantityTable.NewRow();
row3[sizeQuantityColumn] = "Green";
row3[sColumn] = "24";
row3[mColumn] = "27";
this.SizeQuantityTable.Rows.Add(row3);

OK. I have created three columns namely sizeQuantityColumn, sColumn and mColumn and added three rows namely row1, row2 and row2.

So, Let's say I wanna set the selected item as row2 (So in the view, the second row should be highlighted).

How can I do this?

EDIT

I hardcoded the SelectedIndex of the DataGrid to 1. (So the second row should be selected). In design time it shows as selected. But not in the run time. You can see it in the below snapshot.

So ultimaltely the problem is Not highlighting the row.

enter image description here


Solution

  • There are a few way to select items in the DataGrid. It just depends which one works best for the situation

    First and most basic is SelectedIndex this will just select the Row at that index in the DataGrid

     <DataGrid SelectedIndex="{Binding SelectedIndex}" />
    
    private int _selectedIndex;
    public int SelectedIndex
    {
        get { return _selectedIndex; }
        set { _selectedIndex = value; NotifyPropertyChanged("SelectedIndex"); }
    }
    
    SelectedIndex = 2;
    

    SelectedItem will select the row that matches the row you set

    <DataGrid SelectedItem="{Binding SelectedRow}" />
    
    private DataRow _selectedRow;
    public DataRow SelectedRow
    {
        get { return _selectedRow; }
        set { _selectedRow = value; NotifyPropertyChanged("SelectedRow");}
    }
    
    SelectedRow = items.First(x => x.whatever == something);
    

    The most common one is SelectedValue with SelectedValuePath set, in this case you set the column you want to select with and then to can select the row by setting the corresponding value

    <DataGrid SelectedValuePath="Size Quantity" SelectedValue="{Binding SelectionValue}" 
    
    private string _selectedValue
    public string SelectionValue 
    {
        get { return _selectedValue; }
        set { _selectedValue = value; NotifyPropertyChanged("SelectionValue"); }
    }
    
    SelectionValue = "Blue";
    

    Edit:

    Here is my test and it is highlighting just fine

    Code:

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
    
            this.SizeQuantityTable = new DataTable();
            DataColumn sizeQuantityColumn = new DataColumn();
            sizeQuantityColumn.ColumnName = "Size Quantity";
            ...................
            ........
    
        }
    
        private string _selectedValue;
        public string SelectionValue 
        {
            get { return _selectedValue; }
            set { _selectedValue = value; NotifyPropertyChanged("SelectionValue"); }
        }
    
        private int _selectedIndex;
        public int SelectedIndex
        {
            get { return _selectedIndex; }
            set { _selectedIndex = value; NotifyPropertyChanged("SelectedIndex"); }
        }
    
        private DataTable sizeQuantityTable;
        public DataTable SizeQuantityTable
        {
            get { return sizeQuantityTable; }
            set { sizeQuantityTable = value; NotifyPropertyChanged("SizeQuantityTable"); }
        }
    
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            SelectedIndex = 2;
        }
    
        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            SelectionValue = "Blue";
        }
    
        private void NotifyPropertyChanged(string p)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(p));
            }
        }
    }
    

    Xaml:

    <Window x:Class="WpfApplication21.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="202" Width="232" Name="UI">
    
        <Grid DataContext="{Binding ElementName=UI}">
            <DataGrid SelectedValuePath="Size Quantity"        
                      SelectedValue="{Binding SelectionValue}" 
                      SelectedIndex="{Binding SelectedIndex}"
                      ItemsSource="{Binding SizeQuantityTable}"
                      AutoGenerateColumns="True" 
                      Margin="0,0,0,41" />
            <StackPanel Orientation="Horizontal" Height="37" VerticalAlignment="Bottom" >
                <Button Content="SelectedIndex" Height="26"  Width="107" Click="Button_Click_1"/>
                <Button Content="SelectedValue" Height="26"  Width="107" Click="Button_Click_2"/>
            </StackPanel>
        </Grid>
    </Window>
    

    Result:

    enter image description here