如何自动更新 WPF DataGrid 和 xml 之间的绑定

Posted

技术标签:

【中文标题】如何自动更新 WPF DataGrid 和 xml 之间的绑定【英文标题】:How to automatically update Binding between WPF DataGrid and xml 【发布时间】:2021-03-23 22:03:37 【问题描述】:

我有一个 xml 文件并与 WPF DataGrid 绑定。我也有一个更新 xml 文件的方法。 但是在编辑 xml DataGrid 后不会自动更新。是否可以升级 DataGrid?

这是一个 xaml 代码:

        <Window x:Class="TestWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestWPF"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="750" Name ="Window" >
    <Grid Margin="-16,-34,-8,-96">

        <DataGrid x:Name="Dgr_Archive" HorizontalAlignment="Left" Height="215" Margin="25,375,0,0" VerticalAlignment="Top" Width="725"
                  ItemsSource="Binding"  AutoGenerateColumns="False" GridLinesVisibility="Horizontal">
            <DataGrid.DataContext>
                <XmlDataProvider Source="C:\Users\1\source\repos\TestWPF\TestWPF\Archive.xml" XPath="/Companies/Company" />
            </DataGrid.DataContext>
            
            <DataGrid.Columns >
                <DataGridTextColumn Width="25" Header="ID" Binding="Binding XPath=@id">
                <DataGridTextColumn Width="110" Header="Company Name" Binding="Binding XPath=@name"/>
                <DataGridTextColumn Width="110" Header="Position" Binding="Binding XPath=Position"/>
                <DataGridTextColumn Width="110" Header="Address" Binding="Binding XPath=Address"/>
                <DataGridTextColumn Width="110" Header="E mail" Binding="Binding XPath=E_mail"/>
                <DataGridTextColumn Width="119" Header="Contact person" Binding="Binding Path=Contact_person"/>
                <DataGridTextColumn Width="116" Header="Record Timestamp" Binding="Binding XPath=Record_Timestamp"/>
        </DataGrid>
        

    </Grid>
</Window>

这是将记录添加到 xml 的 Code Medhod C#

        private void Add_record(XDocument doc)
        
            XElement n = doc.Root.LastNode as XElement;
            Int32.TryParse(n.Attribute("id").Value, out int LastElementID);

            doc.Root.Add(new XElement("Company",
                       new XElement("Position", Tbx_Position.Text),
                       new XElement("Address", Tbx_Address.Text + "  " + Tbx_PLZOrt.Text),
                       new XElement("E_mail", Tbx_Email.Text),
                       new XElement("Contact_person", Tbx_Person.Text),
                       new XElement("Record_Timestamp", DateTime.Now.ToString()),
                       new XAttribute("name", Tbx_Company_Name.Text.Replace(" ", "_")),
                       new XAttribute("id", (LastElementID + 1))));
            doc.Save(archpath);

【问题讨论】:

您需要在 ItemsSource 中的行上实现 INotifyPropertyChanged 接口 如果您在网格中进行编辑,您的绑定中还需要 mode=TwoWay 【参考方案1】:

我正在为我的所有实体(您在 ItemsSource 中的行项目)使用下面的类。

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace eTabber.Data.Model

    public class PropertyChangedEntity : INotifyPropertyChanged
    
        public void NotifyPropertyChangedRefType<TValue>(ref TValue oldValue, TValue newValue, [CallerMemberName] string name = null)
            where TValue : class
        
            if (string.IsNullOrEmpty(name)) throw new InvalidOperationException("Name cannot be null!");

            if (oldValue == null)
            
                if (newValue != null && !newValue.Equals(oldValue))
                
                    SetAndNotify(ref oldValue, newValue, name);
                
            
            else
            
                if (!oldValue.Equals(newValue))
                
                    SetAndNotify(ref oldValue, newValue, name);
                
            
        

        private void SetAndNotify<TValue>(ref TValue oldValue, TValue newValue, string name) where TValue : class
        
            oldValue = newValue;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        

        public void NotifyPropertyChangedValueType<TValue>(ref TValue oldValue, TValue newValue, [CallerMemberName] string name = null)
        
            if (string.IsNullOrEmpty(name)) throw new InvalidOperationException("Name cannot be null!");

            if (!newValue.Equals(oldValue))
            
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
            

            oldValue = newValue;
        

        public event PropertyChangedEventHandler PropertyChanged;
    

并且可以在你的派生类中像这样使用它:

public class Account : PropertyChangedEntity

    ... 

    DateTime _ModificationsTimestamp;
    /// <summary>
    /// Timestamp for modifications
    /// </summary>
    public DateTime ModificationsTimestamp  get => _ModificationsTimestamp; set => NotifyPropertyChangedValueType(ref _ModificationsTimestamp, value); 

    private HashSet<SetList> _SetLists;

    /// <summary>
    /// Setlistst belonging to this account
    /// </summary>
    public HashSet<SetList> SetLists  get => _SetLists; set => NotifyPropertyChangedRefType(ref _SetLists, value); 

【讨论】:

以上是关于如何自动更新 WPF DataGrid 和 xml 之间的绑定的主要内容,如果未能解决你的问题,请参考以下文章

wpf c# xml修改的方法

如何在 WPF 数据网格上自动滚动

c# wpf datagrid 模板列修改某个单元格,更新所选行另一个单元格的值,如何做到呢?

WPF DataGrid如何获取ItemsSource更新时

在 WPF DataGrid 中使用多个 XML 文档

WPF DataGrid:如何在单击单元格时停止自动滚动?