WPF中如何从XML加载表格并支持编辑与保存(MVVM模式)
核心实现指引(MVVM范式下的DataGrid+XML读写)
1. 调整XAML绑定(贴合MVVM)
你的现有DataGrid绑定可以优化为直接关联ViewModel的集合属性,同时补充双向绑定确保编辑同步:
<TabItem Header="Device Info" Width="100" Height="25" Selected="DeviceTab_Selected" Unloaded="DeviceTab_Unloaded"> <DataGrid Name="DeviceInfoGrid" ItemsSource="{Binding DeviceData}" AlternatingRowBackground="LightBlue" AlternationCount="2" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="Alias" Binding="{Binding Alias, Mode=TwoWay}"/> <DataGridTextColumn Header="Interface Type" Binding="{Binding InterfaceType, Mode=TwoWay}"/> <DataGridTextColumn Header="Resource ID" Binding="{Binding VisaResource, Mode=TwoWay}"/> <DataGridTextColumn Header="MFG" Binding="{Binding Make, Mode=TwoWay}"/> <DataGridTextColumn Header="Model" Binding="{Binding Model, Mode=TwoWay}"/> <DataGridTextColumn Header="Cal Date" Binding="{Binding CalDate, Mode=TwoWay}"/> <DataGridTextColumn Header="Cal Due Date" Binding="{Binding CalDueDate, Mode=TwoWay}"/> </DataGrid.Columns> </DataGrid> </TabItem>
- 给TabItem添加
Selected/Unloaded事件,触发数据加载与保存 - DataGrid的
ItemsSource绑定到ViewModel的DeviceData属性 - 每个列绑定设置
Mode=TwoWay,确保用户编辑能同步回数据源
2. 定义ViewModel核心类
创建MainWindowViewModel,实现INotifyPropertyChanged(WPF绑定必备),封装数据存储与XML读写逻辑:
using System.ComponentModel; using System.Data; using System.Windows; public class MainWindowViewModel : INotifyPropertyChanged { private DataTable _deviceData; public DataTable DeviceData { get => _deviceData; set { _deviceData = value; OnPropertyChanged(nameof(DeviceData)); } } private readonly string _xmlFilePath = "Devices.xml"; // 替换为你的XML文件路径 // 从XML加载数据到DataTable public void LoadDeviceData() { if (System.IO.File.Exists(_xmlFilePath)) { DataSet ds = new DataSet(); ds.ReadXml(_xmlFilePath); DeviceData = ds.Tables[0]; } else { // 文件不存在时创建空表结构 DeviceData = CreateEmptyDeviceTable(); } } // 将DataTable数据保存到XML public void SaveDeviceData() { try { DataSet ds = new DataSet(); ds.Tables.Add(DeviceData.Copy()); ds.WriteXml(_xmlFilePath); } catch (System.Exception ex) { MessageBox.Show($"保存失败: {ex.Message}"); } } // 创建空的仪器信息表结构 private DataTable CreateEmptyDeviceTable() { DataTable table = new DataTable("Devices"); table.Columns.Add("Alias", typeof(string)); table.Columns.Add("InterfaceType", typeof(string)); table.Columns.Add("VisaResource", typeof(string)); table.Columns.Add("Make", typeof(string)); table.Columns.Add("Model", typeof(string)); table.Columns.Add("CalDate", typeof(string)); table.Columns.Add("CalDueDate", typeof(string)); return table; } // INotifyPropertyChanged接口实现 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
3. 主窗口代码(ViewModel关联+事件触发)
在MainWindow.xaml.cs中完成ViewModel与窗口的绑定,并处理Tab页的加载/保存事件:
public partial class MainWindow : Window { private MainWindowViewModel _viewModel; public MainWindow() { InitializeComponent(); _viewModel = new MainWindowViewModel(); DataContext = _viewModel; // 将ViewModel设为窗口数据上下文 } // 标签页选中时加载数据 private void DeviceTab_Selected(object sender, RoutedEventArgs e) { _viewModel.LoadDeviceData(); } // 标签页卸载时保存数据 private void DeviceTab_Unloaded(object sender, RoutedEventArgs e) { _viewModel.SaveDeviceData(); } }
4. 方向确认
你的思路完全正确:用DataTable作为DataGrid的数据源,借助DataSet的ReadXml/WriteXml快速实现XML读写,符合MVVM范式下UI与逻辑分离的要求。
额外注意:
- 如果后续需要更复杂的业务验证或实体行为,可以将DataTable替换为
ObservableCollection<DeviceModel>(自定义实体类),但当前场景下DataTable是更轻量的选择 - 可在保存前增加确认提示,避免误操作导致数据覆盖
内容的提问来源于stack exchange,提问作者ReelThymeOS
相关产品推荐
相关产品推荐

