WPF DataGridTemplateColumn与DataGridComboBoxColumn绑定异常
WPF DataGridTemplateColumn内ComboBox全绑定到最后一条记录的成因
异常表现
相同绑定规则下,DataGridTemplateColumn中自定义的ComboBox所有行选中值均显示最后一条记录,和原生DataGridComboBoxColumn的正常表现不一致,效果如下:
根本原因
- WPF中所有绑定到同一个集合源的ItemsControl,默认会共享同一个
ICollectionView视图实例,该视图维护了一个指向当前选中项的CurrentItem指针,默认情况下ComboBox会和这个指针双向同步。 - 原生
DataGridComboBoxColumn内部做了特殊处理:生成单元格内的ComboBox元素时,会自动将IsSynchronizedWithCurrentItem属性设为False,切断ComboBox和全局集合视图当前项的同步关联,因此每个行的SelectedItem绑定可以正常关联到当前行对应的数据对象。 - 自定义写在
DataTemplate里的ComboBox没有做这个默认配置,IsSynchronizedWithCurrentItem取默认值null,会自动启用和集合视图的当前项同步。DataGrid加载行、复用单元格容器时,集合视图的CurrentItem最终停留在列表最后一条记录,所有行的ComboBox的SelectedItem都会被这个全局当前项覆盖,就出现了全选最后一条的异常。
问题复现代码
<DataGrid ItemsSource="{Binding Path=GUI.SelectedDefinedStream.MassBalanceReferences, Mode=TwoWay}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTemplateColumn Header="Mass Balance Stream"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <!-- 问题代码:未设置IsSynchronizedWithCurrentItem --> <ComboBox ItemsSource="{Binding Source={StaticResource MassBalanceStreams}}" SelectedItem="{Binding Path=MassBalanceStream}"></ComboBox> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridComboBoxColumn ItemsSource="{Binding Source={StaticResource MassBalanceStreams}}" SelectedItemBinding="{Binding Path=MassBalanceStream}" Header="Mass Balance Stream"></DataGridComboBoxColumn> <DataGridTemplateColumn Header="Factor"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBox Text="{Binding Path=Factor, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"></TextBox> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridTemplateColumn Header=""> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Button Content="{materialDesign:PackIcon Kind=Delete}" Style="{StaticResource MaterialDesignFlatButton}" Click="Delete_MassBalanceReference"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
修复方法
只需要给自定义ComboBox显式添加IsSynchronizedWithCurrentItem="False"属性,切断和全局集合视图当前项的同步即可:
<ComboBox ItemsSource="{Binding Source={StaticResource MassBalanceStreams}}" SelectedItem="{Binding Path=MassBalanceStream}" IsSynchronizedWithCurrentItem="False"> </ComboBox>
如果修复后仍存在滚动时选中值跳变的问题,可以根据需求关闭DataGrid的行虚拟化:VirtualizingStackPanel.IsVirtualizing="False",常规场景下仅添加上述属性即可解决问题。
内容的提问来源于stack exchange,提问作者ceds
相关产品推荐
相关产品推荐

