WPF应用中如何将DataGrid导出为XML?遇类型转换异常求助
解决DataGrid导出XML时的InvalidCastException问题
看起来你遇到的核心问题是直接把DataGrid的ItemsSource强制转换为DataTable失败——这很正常,因为WPF里DataGrid的ItemsSource通常绑定的是IEnumerable类型的集合(比如ObservableCollection<你的实体类>、List<T>),而不是直接的DataTable,强行转换肯定会抛InvalidCastException。
下面分两种场景给你解决方案:
场景1:你的ItemsSource本来就来自DataTable(比如绑定的是DataView)
如果你的DataGrid是直接绑定DataTable的DefaultView(也就是ItemsSource = dt.DefaultView;),那可以通过DataView拿到原DataTable:
private void Xml_export() { // 先转成DataView再拿Table DataView dataView = GokartDataGrid.ItemsSource as DataView; if (dataView == null) { MessageBox.Show("无法获取数据源"); return; } DataTable dt = dataView.Table; SaveFileDialog savefile = new SaveFileDialog(); savefile.Filter = "XML 文件 (*.xml)|*.xml"; savefile.CheckFileExists = false; // 新建文件不需要检查是否存在,原来的true会出问题 if (savefile.ShowDialog() == true) { dt.WriteXml(savefile.FileName); MessageBox.Show("导出成功!"); } }
场景2:你的ItemsSource是自定义实体集合(比如ObservableCollection)
如果你的DataGrid绑定的是自定义实体的集合,那需要先把集合转换成DataTable,再导出XML。可以写一个通用的转换方法:
第一步:添加集合转DataTable的通用方法
using System.ComponentModel; using System.Data; using System.Collections.Generic; public static class CollectionExtensions { public static DataTable ConvertToDataTable<T>(this IEnumerable<T> data) { PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T)); DataTable table = new DataTable(); // 先创建列 foreach (PropertyDescriptor prop in properties) { // 处理可空类型 Type columnType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType; table.Columns.Add(prop.Name, columnType); } // 填充行数据 foreach (T item in data) { DataRow row = table.NewRow(); foreach (PropertyDescriptor prop in properties) { // 处理null值,替换成DBNull row[prop.Name] = prop.GetValue(item) ?? DBNull.Value; } table.Rows.Add(row); } return table; } }
第二步:修改你的导出方法
private void Xml_export() { // 替换GokartModel为你实际的实体类型 var dataItems = GokartDataGrid.ItemsSource as IEnumerable<GokartModel>; if (dataItems == null) { MessageBox.Show("没有可导出的数据或数据源类型不匹配"); return; } // 转换为DataTable DataTable dt = dataItems.ConvertToDataTable(); SaveFileDialog savefile = new SaveFileDialog(); savefile.Filter = "XML 文件 (*.xml)|*.xml"; savefile.CheckFileExists = false; if (savefile.ShowDialog() == true) { dt.WriteXml(savefile.FileName); MessageBox.Show("XML导出完成!"); } }
额外注意点
- 如果你用的是.NET Core/.NET 5+,需要安装
System.ComponentModel.TypeConverterNuGet包才能使用TypeDescriptor。 - 把
SaveFileDialog的CheckFileExists设为false,因为你是要创建新文件,不是打开已有的文件,原来的true会导致如果文件不存在就报错。
内容的提问来源于stack exchange,提问作者Dániel Marton
相关产品推荐
相关产品推荐

