You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.TypeConverter NuGet包才能使用TypeDescriptor。
  • 把SaveFileDialog的CheckFileExists设为false,因为你是要创建新文件,不是打开已有的文件,原来的true会导致如果文件不存在就报错。

内容的提问来源于stack exchange,提问作者Dániel Marton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:32:25