1. 源起
<DataGrid Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding DataList}" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserResizeRows="False" CanUserSortColumns="False" > <DataGrid.Columns> <DataGridTextColumn Header="序号" Width="60" Binding="{Binding Id}"/> <DataGridTextColumn Header="名称" Width="*" Binding="{Binding Name}"/> <DataGridTemplateColumn Header="别名" Width="*"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Grid> <TextBox Width="100" Text="{Binding AliasName}"/> </Grid> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> public class MainWindowViewModel : PropertyChangedBase { private List<NotifyModel> _dataList=new List<NotifyModel>(); public List<NotifyModel> DataList { get => _dataList; set => SetValue(ref _dataList, value, nameof(DataList)); } public void InitDataList() { for (int i = 0; i < 10; i++) { var c = (char) (65 + i); DataList.Add(new NotifyModel { Id = i+1, Name = $"{c}{c}{c}", }); } } } /// <summary> /// 用于通知属性变更的基类 /// </summary> public class PropertyChangedBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public void SetValue<T>(ref T field, T value, string propertyName) { if (EqualityComparer<T>.Default.Equals(field, value)) return; field = value; OnPropertyChanged(propertyName); } } public class NotifyModel { public int Id { get; set; } public string Name { get; set; } public string AliasName { get; set; } } 到了这里,我满以为问题就解决了,但是为了保险起见,我还是开了个测试项目,准备测试一下这么干有没有问题(还没有在列表中这么用过^_^)。
2. 意料之外的结果


Binding.Mode属性很清楚的说明了,控件的可编辑属性,默认为双向绑定:
<TextBox Width="100" Text="{Binding AliasName,Mode=TwoWay}"/> 
3.对比
是代码有问题吗?哪里写的不对,导致界面上的变更传播不到数据源?为了对比,在界面上添加了一个新的绑定属性:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="60"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Grid.Row="0" HorizontalAlignment="Right" Orientation="Horizontal"> <TextBlock Text="模块名称" VerticalAlignment="Center" Margin="5"/> <TextBox Text="{Binding ModuleName,Mode=TwoWay}" Width="150" Height="30" VerticalAlignment="Center" TextAlignment="Left" VerticalContentAlignment="Center"/> <Button Content="Test" Width="100" Height="30" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="10,0" Click="Test_OnClick"/> </StackPanel> <DataGrid Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding DataList}" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserResizeRows="False" CanUserSortColumns="False" > <DataGrid.Columns> <DataGridTextColumn Header="序号" Width="60" Binding="{Binding Id}"/> <DataGridTextColumn Header="名称" Width="*" Binding="{Binding Name}"/> <DataGridTemplateColumn Header="别名" Width="*"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Grid> <TextBox Width="100" Text="{Binding AliasName,Mode=TwoWay}"/> </Grid> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> </Grid> private string _moduleName = ""; public string ModuleName { get => _moduleName; set => SetValue(ref _moduleName, value, nameof(ModuleName)); } 

4. 解决过程
Binding类,发现了它有个UpdateSourceTrigger属性,文档中对它的介绍是:
Gets or sets a value that determines the timing of binding source updates. 获取或设置一个值,该值确定绑定源的更新时机。
One of the UpdateSourceTrigger values. The default is Default, which returns the default UpdateSourceTrigger value of the target dependency property. However, the default value for most dependency properties is PropertyChanged, while the Text property has a default value of LostFocus. UpdateSourceTrigger属性取UpdateSourceTrigger枚举的值之一。默认值为Default,该值返回目标依赖属性的默认UpdateSourceTrigger值。但是,对于大多数依赖属性来说,默认值为PropertyChanged,而Text属性的默认值为LostFocus。
<TextBox Width="100" Text="{Binding AliasName,Mode=TwoWay,UpdateSourceTrigger=LostFocus}"/> 

5. 源码
来源:博客园
作者:stonemqy
链接:https://www.cnblogs.com/stonemqy/p/11684421.html