WPF DataGrid修改列值后目标数据不显示的问题排查与解决
WPF DataGrid 数据更新后界面不实时显示的问题解决
在C# WPF项目中使用DataGrid,ItemsSource从后台代码填充时遇到两个问题:
- 为某列设置默认值后,该值需双击列才会显示;
- 在CellEndEdit事件中修改另一列的值时,无法实时显示,需双击进入编辑状态才可见。
已尝试以下刷新方法均无效:
DGR_SUB_INVOLST.Items.Refresh(); DGR_SUB_INVOLST.BeginEdit(); DGR_SUB_INVOLST.CommitEdit(); DGR_SUB_INVOLST.InvalidateVisual(); DGR_SUB_INVOLST.UpdateLayout();
相关代码
XAML
<DataGrid x:Name="DGR_SUB_INVOLST" EnableColumnVirtualization="True" EnableRowVirtualization="True" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ScrollViewer.CanContentScroll="False" ItemsSource="{Binding ALL_DATA_INVO, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" AutoGenerateColumns="False" FlowDirection="RightToLeft" CellEditEnding="DGR_SUB_INVOLST_CellEditEnding" SelectionUnit="Cell"> <DataGrid.Columns > <DataGridTextColumn Header="ردیف" x:Name="RADIF_COL" Binding="{Binding RADIF}" MinWidth="40" Visibility="Hidden"/> <DataGridComboBoxColumn x:Name="ANBAR_COL" Width="80" Header=" انبار " SelectedValueBinding="{Binding CODE,UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="NAMES" SelectedValuePath="CODE"> <DataGridComboBoxColumn.EditingElementStyle> <Style TargetType="{x:Type ComboBox}"> <Setter Property="IsEditable" Value="True"/> <Setter Property="ItemsPanel" Value="{StaticResource VSP}"/> <Setter Property="ScrollViewer.CanContentScroll" Value="True"/> <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"/> <Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling"/> </Style> </DataGridComboBoxColumn.EditingElementStyle> </DataGridComboBoxColumn> <DataGridTextColumn Header="نام کالا" x:Name="NAME_COL" Binding="{Binding NAME,UpdateSourceTrigger=PropertyChanged}" Visibility="Visible" MinWidth="180"/> <DataGridTextColumn Header="کد کالا" x:Name="CODEKALA_COL" Binding="{Binding CODEKALA,UpdateSourceTrigger=PropertyChanged}" Visibility="Hidden" MinWidth="80"/> </DataGrid.Columns> </DataGrid>
C#
private void DGR_SUB_INVOLST_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) { if (DGR_SUB_INVOLST != null) { if (DGR_SUB_INVOLST.Items.Count > 0) { (e.Row.Item as INVOMonitor).CODE = 1; //Refresh here : DGR_SUB_INVOLST.Items.Refresh(); DGR_SUB_INVOLST.BeginEdit(); DGR_SUB_INVOLST.CommitEdit(); DGR_SUB_INVOLST.InvalidateVisual(); DGR_SUB_INVOLST.UpdateLayout(); } } }
解决方案
问题根源是INVOMonitor类未实现INotifyPropertyChanged接口,WPF数据绑定依赖该接口监听属性变化,自动同步界面显示。
1. 修改INVOMonitor类实现接口
public class INVOMonitor : INotifyPropertyChanged { private int _code; public int CODE { get => _code; set { if (_code != value) { _code = value; OnPropertyChanged(nameof(CODE)); } } } // 其他需要绑定的属性(如RADIF、NAME等)都要按此方式实现 private int _radif; public int RADIF { get => _radif; set { if (_radif != value) { _radif = value; OnPropertyChanged(nameof(RADIF)); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. 简化CellEditEnding事件代码
移除所有手动刷新代码,属性变更会自动通知界面更新:
private void DGR_SUB_INVOLST_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) { if (e.Row.Item is INVOMonitor item) { item.CODE = 1; } }
原理说明
WPF绑定机制通过INotifyPropertyChanged的PropertyChanged事件,在属性值变更时通知DataGrid列更新显示。若实体类未实现该接口,即使修改属性值,界面也无法感知变化;手动刷新方法在虚拟化开启场景下往往无效,且不符合WPF绑定规范。
内容的提问来源于stack exchange,提问作者Learner
相关产品推荐
相关产品推荐

