Как автоматически обновлять привязку между сеткой данных WPF и xml

#c# #xml #wpf

#c# #xml #wpf

Вопрос:

У меня есть XML-файл и привязка к сетке данных WPF. Также у меня есть метод, который обновляет XML-файл. Но после редактирования xml 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:Users1sourcereposTestWPFTestWPFArchive.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>
 

И вот код Medhod C # для добавления записи в xml

         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);
 

Комментарии:

1. Вам нужно будет реализовать интерфейс INotifyPropertyChanged для строк в вашем ItemsSource

2. Если вы редактируете в сетке, вам также понадобится 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 amp;amp; !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); }
}