2

after trying a lot of (not working) solutions, I hope someone can help me.

If the focus of the selected row in my DataGrid is lost, the selected value of the ComboBox column will also be lost.

This is my XAML-Code

<Window x:Class="DataGridComboBoxTest.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:DataGridComboBoxTest"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <DataGrid Name="dataGrid"></DataGrid>
</Grid>

And her is the CS Code:

using System.Collections.Generic;
using System.Data;
using System.Windows;
using System.Windows.Controls;

namespace DataGridComboBoxTest
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            //Some Sample Data

            DataTable dataTable = new DataTable();
            dataTable.Columns.Add("Name");
            dataTable.Columns.Add("Age");

            DataRow dataRow1 = dataTable.NewRow();
            dataRow1["Name"] = "John";
            dataRow1["Age"] = "33";
            dataTable.Rows.Add(dataRow1);

            DataRow dataRow2 = dataTable.NewRow();
            dataRow2["Name"] = "Emily";
            dataRow2["Age"] = "19";
            dataTable.Rows.Add(dataRow2);

            this.dataGrid.ItemsSource = dataTable.DefaultView;

            //Add ComboBox Column
            Dictionary<string, string> genders = new Dictionary<string, string>();
            genders.Add("f", "female");
            genders.Add("m", "male");

            DataGridComboBoxColumn dgCmbColumn = new DataGridComboBoxColumn();
            dgCmbColumn.Header = "Gender";

            dgCmbColumn.SelectedValuePath = "Key";
            dgCmbColumn.DisplayMemberPath = "Value";
            dgCmbColumn.ItemsSource = genders;


            this.dataGrid.Columns.Add(dgCmbColumn);
        }
    }
}

I tried a lot of solutions with Bindings, but nothing works for me.

ToM_ToM
  • 23
  • 2
  • Binding is far quicker and easier, consider using a VM instead of code-behind, then create and use a property 'SelectedGender' in your VM as the 'SelectedItemBinding' in the DatagridComboboxColumn. – rufw91 Jul 02 '20 at 11:10

2 Answers2

1

If the focus of the selected row in my DataGrid is lost, the selected value of the ComboBox column will also be lost.

That's because you don't store the currently selected value somewhere.

Add a column to your DataTable:

dataTable.Columns.Add("Gender");

...and set the SelectedValueBinding property of the column:

dgCmbColumn.SelectedValueBinding = new Binding("Gender");
mm8
  • 163,881
  • 10
  • 57
  • 88
  • But if I scroll down so far that the items getting invisible and scroll up again, the Values will be lost again. I guess that the binding is not working properly. – ToM_ToM Jul 02 '20 at 18:20
  • @ToM_ToM: If you debug your code and look at the current value of the `ItemsSource`, does it contain any "Gender" column and values? – mm8 Jul 03 '20 at 13:18
  • Yes It contains a Gender column, but without any values. – ToM_ToM Jul 03 '20 at 13:45
  • @ToM_ToM: And the `ItemsSource` of the `ComboBox` is still a `Dictionary`? – mm8 Jul 03 '20 at 13:46
  • Yes, It is. `DataTable dataTable = new DataTable(); dataTable.Columns.Add("Name"); dataTable.Columns.Add("Age"); dataTable.Columns.Add("Gender");` `Dictionary genders = new Dictionary(); genders.Add("f", "female"); genders.Add("m", "male");` – ToM_ToM Jul 03 '20 at 17:52
  • @ToM_ToM: Could you please edit your question with what you currently have then? – mm8 Jul 06 '20 at 13:33
0

I suggest defining your columns in XAML as it is more readable than in code-behind:

<DataGrid Name="dataGrid" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
        <DataGridTextColumn Header="Age" Binding="{Binding Age}"/>
        <DataGridComboBoxColumn Header="Gender" SelectedItemBinding="{Binding Gender}" x:Name="myComboBoxColumn"/>
    </DataGrid.Columns>
</DataGrid>

In your code-behind, do not forget to also define a data column for the gender:

dataTable.Columns.Add("Gender");

For easy manipulation of gender, let's create an enum:

public enum Gender { Male, Female, Other }

And finally, set the ItemsSource of your column to your list of genders:

myComboBoxColumn.ItemsSource = new Gender[] { Gender.Male, Gender.Female, Gender.Other };

Total code-behind becomes:

InitializeComponent();

//Some Sample Data

DataTable dataTable = new DataTable();
dataTable.Columns.Add("Name");
dataTable.Columns.Add("Age");
dataTable.Columns.Add("Gender");

DataRow dataRow1 = dataTable.NewRow();
dataRow1["Name"] = "John";
dataRow1["Age"] = "33";
dataTable.Rows.Add(dataRow1);

DataRow dataRow2 = dataTable.NewRow();
dataRow2["Name"] = "Emily";
dataRow2["Age"] = "19";
dataTable.Rows.Add(dataRow2);

this.dataGrid.ItemsSource = dataTable.DefaultView;
myComboBoxColumn.ItemsSource = new Gender[] { Gender.Male, Gender.Female, Gender.Other };
Corentin Pane
  • 4,794
  • 1
  • 12
  • 29