如何从代码后台访问资源字典中的CollectionViewSource以重置DataGrid数据?
解决DataGrid取消新增时恢复初始状态的问题
我来给你捋捋怎么搞定这个需求——既然你的CollectionViewSource(简称CVS)藏在ResourceDictionary里,后台代码不是直接拿不到嘛,其实有办法绕开这个限制,核心思路是先保存初始数据的副本,取消时把副本替换回去,具体步骤如下:
1. 从资源字典里获取CVS实例
后台代码可以用FindResource方法找到定义在资源里的CVS,只要你知道它的键名就行:
// 替换成你自己的CVS键名,比如"YourDataCVS" var dataCvs = (CollectionViewSource)this.FindResource("YourDataCVS");
如果CVS是在应用级别的ResourceDictionary里,就换成Application.Current.FindResource("YourDataCVS")来获取。
2. 提前保存初始数据的深拷贝
在页面加载、数据首次绑定的时候,一定要把原始数据做个深拷贝存起来——要是只做浅拷贝,后续修改DataGrid里的数据会连带着修改副本,那就白存了。举个例子,假设你的数据源是ObservableCollection<YourDataModel>:
// 类级别的变量,用来存原始数据副本 private ObservableCollection<YourDataModel> _originalDataBackup; private void Window_Loaded(object sender, RoutedEventArgs e) { var dataCvs = (CollectionViewSource)this.FindResource("YourDataCVS"); var currentSource = dataCvs.Source as ObservableCollection<YourDataModel>; // 这里用Json序列化/反序列化做深拷贝,需要引用Newtonsoft.Json _originalDataBackup = JsonConvert.DeserializeObject<ObservableCollection<YourDataModel>>( JsonConvert.SerializeObject(currentSource) ); // 要是不想用第三方库,也可以手动遍历每个对象复制属性: // _originalDataBackup = new ObservableCollection<YourDataModel>(); // foreach (var item in currentSource) // { // _originalDataBackup.Add(new YourDataModel // { // Id = item.Id, // Name = item.Name, // // 把模型的所有属性都复制一遍 // }); // } }
3. 取消操作时恢复原始数据
当用户点击取消按钮时,把当前CVS的数据源替换回我们保存的副本就行,有两种方式可选:
方式一:清空当前集合,再添加原始数据
这种方式适合不想改变集合引用的场景:
private void CancelBtn_Click(object sender, RoutedEventArgs e) { var dataCvs = (CollectionViewSource)this.FindResource("YourDataCVS"); var currentCollection = dataCvs.Source as ObservableCollection<YourDataModel>; currentCollection.Clear(); // 注意这里最好也复制一遍副本里的对象,避免后续修改影响备份 foreach (var item in _originalDataBackup) { currentCollection.Add(new YourDataModel { Id = item.Id, Name = item.Name }); } }
方式二:直接替换CVS的Source
这种方式更简洁,直接给CVS的Source赋值新的集合:
private void CancelBtn_Click(object sender, RoutedEventArgs e) { var dataCvs = (CollectionViewSource)this.FindResource("YourDataCVS"); // 同样要做一次对象复制,保证备份不被修改 var restoredCollection = new ObservableCollection<YourDataModel>( _originalDataBackup.Select(item => new YourDataModel { Id = item.Id, Name = item.Name }) ); dataCvs.Source = restoredCollection; }
额外小贴士
如果你的项目用了MVVM模式,其实更推荐把CVS的Source绑定到ViewModel里的可观察集合,这样不用在后台找资源,直接在ViewModel里维护原始数据副本,取消时更新绑定的集合就行,代码会更整洁:
<CollectionViewSource x:Key="YourDataCVS" Source="{Binding YourDataCollection}" />
内容的提问来源于stack exchange,提问作者mcalex
相关产品推荐
相关产品推荐

