Search code examples
c#wpfcomboboxdatagriddatagridcomboboxcolumn

WPF Combox in DataGrid - SelectionChanged event returning selected ComboBoxItem as null


Question: Inside the SelectionChanged event of Combobox in DataGrid, the ComboboxItem is always null. What I may be missing and how we can fix the issue? Please note that (as shown in image 1) if you are able to select an item from the combobox, that means the combobox has already been loaded. And hence it's SelectionChanged event is called after combobox got loaded.

Employee.cs:

public class Employee
{
    public int EmployeeId { get; set; }
    public string Name { get; set; }
    public string StateName { get; set; }
}

State.cs:

public class State
{
    public string StateName { get; set; }
    public string StateCode { get; set; }
}

StateList.cs:

public class StateList : List<State>
{
    public StateList()
    {
        Add(new State { StateName = "Iowa", StateCode = "IA" });
        Add(new State { StateName = "Nebraska", StateCode = "NE" });
        Add(new State { StateName = "Ohio", StateCode = "OH" });
        Add(new State { StateName = "Virginia", StateCode = "VA" });
    }
}

Combobox SelectionChanged event [always returns cmbItem as null]:

private void cmbState_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    StateList states = new StateList();
    string st = "";
    ComboBoxItem cmbItem = ((sender as ComboBox).SelectedItem as ComboBoxItem);
    if(cmbItem != null)
        st = "   You selected " + cmbItem.Content.ToString() + ".";
}

Snapshot of changing the selection:

enter image description here

ComboboxItem showing as null:

enter image description here

MainWindow.xaml:

<Window x:Class="WPF_DataGridCombobox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        .......
        Title="MainWindow" Height="450" Width="800">

    <Window.Resources>
        <local:StateList x:Key="ListOfStates"/>
    </Window.Resources>
    <Grid>
        <DataGrid x:Name="dgEmplyees" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Update">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button x:Name="btnUpdate" Click="btnUpdate_Click"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Header="Name" Binding="{Binding  Name}"/>
                <DataGridTemplateColumn Header="State Name">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding StateName}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <ComboBox x:Name="cmbState" ItemsSource="{StaticResource ListOfStates}" DisplayMemberPath="StateName" SelectedValuePath="StateName" SelectedValue="{Binding StateName}" SelectionChanged="cmbState_SelectionChanged" IsEditable="False" IsReadOnly="True" />                            
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

Solution

  • ((ComboBox)sender).SelectedItem as ComboBoxItem
    

    is null because SelectedItem is not a ComboBoxItem. It would be a ComboBoxItem if you had explicitly added ComboBoxItems, e.g. like

    <ComboBox>
        <ComboBoxItem>Item 1</ComboBoxItem>
        <ComboBoxItem>Item 2</ComboBoxItem>
    <ComboBox>
    

    Since you have assiged a collection of State objects to the ItemsSource property of the ComboBox, SelectedItem is a State object:

    private void cmbState_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var state = (State)((ComboBox)sender).SelectedItem;
        ...
    }