XAML:
<Window x:Class="WpfApplication1.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:WpfApplication1" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Grid> <DataGrid SelectionMode="Single" IsReadOnly="False" AutoGenerateColumns="False" x:Name="dg" ItemsSource="{Binding UsersList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" RowEditEnding="DataGrid_RowEditEnding" CellEditEnding="dg_CellEditEnding"> <DataGrid.Columns> <DataGridTemplateColumn Header="Nation"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding UserNation,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <ComboBox ItemsSource="{Binding Source={x:Static local:MainWindow.NationsList}}" SelectedIndex="0" SelectedValue="{Binding UserNation,UpdateSourceTrigger=LostFocus}"/> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn> <!--<DataGridComboBoxColumn Header="Nation" SelectedValueBinding="{Binding UserNation}" ItemsSource="{Binding Source={x:Static local:MainWindow.NationsList}}"> <DataGridComboBoxColumn.EditingElementStyle> <Style TargetType="{x:Type ComboBox}"> <EventSetter Event="SelectionChanged" Handler="NationSelectionChanged"/> </Style> </DataGridComboBoxColumn.EditingElementStyle> </DataGridComboBoxColumn>--> <DataGridCheckBoxColumn Header="CanEnglish" IsThreeState="False" Binding="{Binding CanEnglish,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> <DataGridTextColumn Header="Name" Binding="{Binding Name,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> <!--<DataGridComboBoxColumn Header="Grade" SelectedValueBinding="{Binding UserGrade}" ItemsSource="{Binding Source={x:Static local:MainWindow.GradesList}}"> <DataGridComboBoxColumn.EditingElementStyle> <Style TargetType="{x:Type ComboBox}"> <EventSetter Event="SelectionChanged" Handler="GradeSelectionChanged"/> </Style> </DataGridComboBoxColumn.EditingElementStyle> </DataGridComboBoxColumn>--> <DataGridTemplateColumn Header="Grade"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding UserGrade,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <ComboBox ItemsSource="{Binding Source={x:Static local:MainWindow.GradesList}}" SelectedIndex="0" SelectedValue="{Binding UserGrade,UpdateSourceTrigger=LostFocus}"/> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> </Grid> </Window>
CS:
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.IO; using System.Collections.ObjectModel; using System.Data; namespace WpfApplication1 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public static List<string> GradesList { get; set; } public List<User> UsersList { get; set; } public static List<string> NationsList { get; set; } static MainWindow() { NationsList = new List<string>() { "USA", "UK", "JAPAN" }; GradesList = new List<string>() { "1", "2", "3" }; } public MainWindow() { InitializeComponent(); this.DataContext = this; InitDataSource(); } private void InitDataSource() { UsersList = new List<User>(); string jsonValue = File.ReadAllText("users.log"); UsersList = JsonConvert.DeserializeObject<List<User>>(jsonValue); } public void NationSelectionChanged(object sender,SelectionChangedEventArgs e) { var comboBox = sender as ComboBox; if (comboBox.SelectedItem != null) { var index = dg.SelectedIndex; if(index>0) { var selectedUser = dg.SelectedItem as User; if(selectedUser!=null) { string newNation = (sender as ComboBox).SelectedItem as string; selectedUser.UserNation = newNation; UsersList.RemoveAt(index); UsersList.Insert(index, selectedUser); string json = JsonConvert.SerializeObject(UsersList, Formatting.Indented); File.WriteAllText("users.log", json, Encoding.UTF8); } } } } public void GradeSelectionChanged(object sender, SelectionChangedEventArgs e) { var comboBox = sender as ComboBox; if (comboBox.SelectedItem != null) { var index = dg.SelectedIndex; if (index > 0) { var selectedUser = dg.SelectedItem as User; if (selectedUser != null) { string newGrade = (sender as ComboBox).SelectedItem as string; selectedUser.UserGrade = newGrade; UsersList.RemoveAt(index); UsersList.Insert(index, selectedUser); string json = JsonConvert.SerializeObject(UsersList, Formatting.Indented); File.WriteAllText("users.log", json, Encoding.UTF8); } } } } private void DataGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e) { var selectedUser= e.Row.DataContext as User; if(selectedUser!=null) { UpdateUsersList(selectedUser); } } private void dg_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) { var selectedUser = e.Row.Item as User; if(selectedUser!=null) { UpdateUsersList(selectedUser); } } private void UpdateUsersList(User selectedUser) { if(UsersList!=null && UsersList.Any()) { var index = dg.SelectedIndex; if (index >= 0) { var newUser = new User() { UserNation = selectedUser.UserNation, Name = selectedUser.Name, CanEnglish = selectedUser.CanEnglish, UserId = selectedUser.UserId, UserGrade = selectedUser.UserGrade }; UsersList.RemoveAt(index); UsersList.Insert(index, newUser); string json = JsonConvert.SerializeObject(UsersList, Formatting.Indented); File.WriteAllText("users.log", json, Encoding.UTF8); } } } } public class User { public string UserNation { get; set; } public string Name { get; set; } public bool CanEnglish { get; set; } public int UserId { get; set; } public string UserGrade { get; set; } } public class Nation { public string NationName { get; set; } public string Code { get; set; } } public class Grade { public string GradeName { get; set; } public int GradeIndex { get; set; } } }
This is the key role
<DataGridTemplateColumn Header="Grade"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding UserGrade,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <ComboBox ItemsSource="{Binding Source={x:Static local:MainWindow.GradesList}}" SelectedIndex="0" SelectedValue="{Binding UserGrade,UpdateSourceTrigger=LostFocus}"/> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn>
WPF Datagrid contains ComboBox while display textblock when display and combobox in editing mode