ViewModel更新后DataGrid未同步刷新问题求助
问题解决:DataGrid绑定DataTable后UI不刷新
问题原因
WPF的DataTable对结构变更(增删列)的通知支持有限,即便ViewModel实现了INotifyPropertyChanged,直接修改现有DataTable实例的列/行后,仅调用OnPropertyChanged有时无法触发DataGrid重新生成列或刷新UI。另外你当前代码是直接修改KalenderKerjaTable的现有实例,而非替换为新实例,这会导致绑定系统无法识别有效的变更通知。
解决方案
方案1:替换为新的DataTable实例(推荐)
不要直接修改现有KalenderKerjaTable的列和行,而是创建新的DataTable实例,完成数据填充后再赋值给属性,这样OnPropertyChanged会完全触发绑定更新:
修改GetWorkingCalendar方法中的相关代码:
private async void GetWorkingCalendar() { // 清空HariKerjaTable(若需保留实例则直接清空,否则可直接赋值新实例) HariKerjaTable?.Clear(); // 创建新的KalenderKerjaTable实例,避免修改现有实例 var newKalenderTable = new DataTable(); var data = new { month = Month, year = Year, }; string get = await BaseAPI.PostMethod("calendar/select", JsonConvert.SerializeObject(data)); if (get is not null) { JObject jsonObject = JObject.Parse(get); JToken dataToken = jsonObject["data"]; HariKerjaTable = dataToken.ToObject<DataTable>(); } else { MessageBox.Show("Something wrong when retrieving", "Null", MessageBoxButton.OK, MessageBoxImage.Error); } // await后已回到UI线程,无需手动调用Dispatcher.Invoke foreach (DataRow row in HariKerjaTable.Rows) { DateTime date = DateTime.Parse(row["date_calendar"].ToString()); Debug.WriteLine(date.ToString("ddd\ndd")); if (!newKalenderTable.Columns.Contains(date.ToString("ddd\ndd"))) { newKalenderTable.Columns.Add(date.ToString("ddd\ndd")); } } // 赋值新实例,触发PropertyChanged通知UI更新 KalenderKerjaTable = newKalenderTable; Debug.WriteLine("+++++++++++++++++++++++++++++++"); foreach (DataColumn column in KalenderKerjaTable.Columns) { Debug.WriteLine(column.ColumnName); } }
方案2:强制DataGrid刷新(临时方案)
如果必须保留现有DataTable实例,可以在修改完成后强制DataGrid重新绑定:
- 给XAML中的
DataGrid添加命名:
<Grid Grid.Row="1" Margin="0,5,0,0"> <DataGrid x:Name="KalenderDataGrid" ItemsSource="{Binding KalenderKerjaTable}" FrozenColumnCount="2" AutoGenerateColumns="True"/> </Grid>
- 在修改完列后执行:
KalenderDataGrid.ItemsSource = null; KalenderDataGrid.ItemsSource = KalenderKerjaTable;
这种方式不够优雅,仅适合临时场景,不推荐作为长期解决方案。
额外优化点
- 移除不必要的
Application.Current.Dispatcher.Invoke:await异步方法后,默认会回到调用时的同步上下文(UI线程),无需手动切换线程。 - 初始化
HariKerjaTable:在ViewModel构造函数中添加HariKerjaTable = new DataTable();,避免后续调用Rows时出现空引用异常。
内容的提问来源于stack exchange,提问作者Exto Logia
相关产品推荐
相关产品推荐

