跳转到主要内容
杨月昌的软件博客
返回

WPF 实战:将 DataGrid 数据导出为 XML 文件

1. 业务场景与数据结构

在林业管理或城市绿化系统中,我们需要将界面上展示的树木信息进行本地归档。XML 格式因其良好的结构性和通用性,是存储此类数据的理想选择。

预期的 XML 结构示例:

<Tree>
  <Item>
    <编号>T1</编号>
    <树冠>3.3m</树冠>
    <树干>22cm</树干>
    <树龄>50</树龄>
    <古树等级>二级</古树等级>
  </Item>
</Tree>

2. 数据模型 (Model) 定义

使用 C# 的自动属性可以极大精简模型类。我们定义 DataTree 类来承载每一行数据。

public class DataTree
{
    public string Number { get; set; }
    public string Crown { get; set; }
    public string Trunk { get; set; }
    public string Age { get; set; }
    public string Grade { get; set; }

    public DataTree() { }

    public DataTree(string number, string crown, string trunk, string age, string grade)
    {
        Number = number;
        Crown = crown;
        Trunk = trunk;
        Age = age;
        Grade = grade;
    }
}

3. 界面设计 (XAML)

在 XAML 中,我们为保存按钮配置样式。为了提升用户体验,我们使用了图片背景并添加了 ToolTip 提示。

<Button x:Name="btSaveTree" 
        ToolTip="保存数据到XML" 
        Width="32" Height="32" 
        Click="BtSaveTree_Click">
    <Button.Background>
        <ImageBrush ImageSource="img/save_icon.png" />
    </Button.Background>
</Button>

4. 核心保存逻辑实现

SaveData 类中,我们重点优化了资源管理。通过 using 块,可以确保 XmlWriter 在操作完成后自动关闭并释放文件流。

SaveData 服务类

using System.Xml;
using System.Text;
using System.IO;
using System.Collections.Generic;

public class SaveService
{
    /// <summary>
    /// 将列表数据保存为XML
    /// </summary>
    /// <param name="dataList">待保存的数据集合</param>
    /// <param name="folderName">分类文件夹名</param>
    public void SaveTreeData(IEnumerable<DataTree> dataList, string folderName)
    {
        // 构建存储路径
        string baseDir = AppDomain.CurrentDomain.BaseDirectory;
        string dirPath = Path.Combine(baseDir, "Resource", "XML", folderName);
        
        if (!Directory.Exists(dirPath))
            Directory.CreateDirectory(dirPath);

        string filePath = Path.Combine(dirPath, $"{folderName}.xml");

        // 配置XML写入参数
        XmlWriterSettings settings = new XmlWriterSettings
        {
            Indent = true,            // 启用缩进
            Encoding = Encoding.UTF8, // 使用UTF8编码
            NewLineChars = "\r\n"
        };

        // 使用 using 确保资源释放
        using (XmlWriter writer = XmlWriter.Create(filePath, settings))
        {
            writer.WriteStartElement("Tree");

            foreach (var tree in dataList)
            {
                writer.WriteStartElement("Item");
                writer.WriteElementString("编号", tree.Number);
                writer.WriteElementString("树冠", tree.Crown);
                writer.WriteElementString("树干", tree.Trunk);
                writer.WriteElementString("树龄", tree.Age);
                writer.WriteElementString("古树等级", tree.Grade);
                writer.WriteEndElement();
            }

            writer.WriteEndElement(); // End Tree
            writer.Flush();
        }
    }
}

5. UI 层的事件调用

MainWindow.xaml.cs 中,我们从 DataGridItemsSource 中提取数据并传递给服务类。

private void BtSaveTree_Click(object sender, RoutedEventArgs e)
{
    try
    {
        // 假设 DataGrid 绑定的是 DataView 或 List<DataTree>
        if (dgTree.ItemsSource is DataView dv)
        {
            var list = new List<DataTree>();
            foreach (DataRowView row in dv)
            {
                list.Add(new DataTree(
                    row["编号"].ToString(), 
                    row["树冠"].ToString(), 
                    row["树干"].ToString(), 
                    row["树龄"].ToString(), 
                    row["古树等级"].ToString()));
            }

            SaveService service = new SaveService();
            service.SaveTreeData(list, "TreeData_2024");
            
            MessageBox.Show("数据保存成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"保存失败: {ex.Message}");
    }
}


上一篇
WPF 实战:构建企业级全局异常捕获与 log4net 日志监控系统
下一篇
给 Hexo 加个后台,轻松实现博客在线管理