Сериализация в XML WPF

194
22 июля 2018, 18:20

Подскажите пожалуйста, что я делаю не правильно. Пробую сохранять в xml файле получается, но обратно в таблицу загрузка не происходит, подскажите в чём моя ошибка? Спасибо.

<Window x:Class="XmlSearilization.MainWindow"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <DataGrid Name="grd" Grid.Row="0"  ItemsSource="{Binding All}" 
                          AutoGenerateColumns="False" CanUserAddRows="True">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding id}" Header="№" IsReadOnly="True" Width="Auto" />
                <DataGridTextColumn Binding="{Binding Name}" Header="Имя" Width="Auto"/>
                <DataGridTextColumn Binding="{Binding SecondName}" Header="Фамилия" Width="Auto"/>
            </DataGrid.Columns>
        </DataGrid>
        <StackPanel Margin="2" Grid.Row="1" Orientation="Horizontal">
            <Button Command="{Binding SaveCommand}" Margin="5"
                            Click="Button_Click">Сохранить в XML</Button>
        </StackPanel>
    </Grid>
</Window>
[Serializable]
public class Settings
{
    public static string Path = "config.xml";
}
public class Person : ViewModelBase
{
    public int id
    {
        get { return ID; }
        set
        {
            ID = value;
            base.RaisePropertyChangedEvent("id");
        }
    }
    private int ID { get; set; }
    public string Name { get; set; }
    public string SecondName { get; set; }
    public Person()
    { }
    public static void Save(string path, Person[] subds)
    {
        XmlSerializer formatter = new XmlSerializer(subds.GetType());
        using (FileStream fs = new FileStream(path, FileMode.Create))
        {
            formatter.Serialize(fs, subds);
        }
    }
    public static IEnumerable<Person> Load(string path)
    {
        XmlSerializer formatter = new XmlSerializer(typeof(Person[]));
        if (File.Exists(path))
            using (FileStream fs = new FileStream(path, FileMode.Open))
            {
                var subds = formatter.Deserialize(fs) as Person[];
                if (subds != null)
                    return subds;
            }
        return Enumerable.Empty<Person>();
    }
}
public class MainViewModel : ViewModelBase
{
    private ICommand saveCommand;
    public ObservableCollection<Person> All { get; set; }
    public void Save(object p = null)
    {
        Person.Save(Settings.Path, All.ToArray());
    }
    public MainViewModel(IEnumerable<Person> all)
    {
        All = new ObservableCollection<Person>(all);
        saveCommand = new RelayCommand(Save);
    }
    public MainViewModel() : this(Person.Load(Settings.Path))
    {
        All = new ObservableCollection<Person>();
        All.CollectionChanged += OnGroceryListChanged;
        this.All = NumberService.SetCollection(this.All);
    }
    void OnGroceryListChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        NumberService.SetCollection(this.All);
    }
    public ICommand SaveCommand
    {
        get { return saveCommand; }
        set { saveCommand = value; }
    }
}
public class RelayCommand : ICommand
{
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;
    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    public void Execute(object parameter)
    {
        _execute(parameter);
    }
}
public static class NumberService
{
    public static ObservableCollection<T> SetCollection<T>(ObservableCollection<T>
       targetCollection) where T : Person
    {
        // Initialize
        var Number = 1;
        // Resequence
        foreach (Person sequencedObject in targetCollection)
        {
            sequencedObject.id = Number;
            Number++;
        }
        // Set return value
        return targetCollection;
    }
}
Answer 1

Десериализация срабатывает нормально.

Обратите внимание на свой конструктор без параметров:

public MainViewModel() : this(Person.Load(Settings.Path))
{
    All = new ObservableCollection<Person>();
    All.CollectionChanged += OnGroceryListChanged;
    this.All = NumberService.SetCollection(this.All);
}

После успешной загрузки данных во втором конструкторе, который вы вызываете через this(...), вы затираете коллекцию: All = new ObservableCollection<Person>(), думаю, эта строчка здесь лишняя.

При использовании отладчика такие ошибки отлавливаются очень легко, обязательно научитесь им пользоваться.

Как и какими средствами находить ошибки в коде на C#?

READ ALSO
Обобщение для операций с таблицами в одной модели Entity Framework

Обобщение для операций с таблицами в одной модели Entity Framework

Есть много таблиц в одной модели, созданной при помощи Code FirstС каждой из них нужно проделать одинаковые операции

168
Ограничить нагрузку на процессор

Ограничить нагрузку на процессор

Пишу что-то вроде софтины для сервера, позволяющей удобно поднимать разные bat-ники ("сервера") из одного места, сохранять их настройки и аргументы...

145
Как удалить загруженную рекламу в AdMob?

Как удалить загруженную рекламу в AdMob?

Я инициализирую и загружаю рекламу на старте:

145
С# выяснить содержимое листа при GetType().GetFields

С# выяснить содержимое листа при GetType().GetFields

Мы узнаем количество полей и их значение в классе следующим образом

175