Отмена изменений объекта MVVM WPF EF6

125
05 декабря 2019, 07:20

У меня есть проект для моего колледжа. В нем я пытаюсь реализовать MVVM + WPF + EF6. По ходу возникла проблема, которую я не могу решить уже слишком долго.

Немного о том что я уже смог сделать:

Есть класс MedRecordViewModel - view model с свойством selecteditem и определёнными CRUD командами, есть view MedRecordEdit в которую передаётся в качестве datacontexts'a - MedRecordViewModel.

Суть проблемы: Я не могу сделать отмену изменений, которые сразу же применяются из-за реализованного inotifypropertychanged интерфейса.

Я нашел решение по типу "создать клон объекта с помощью AutoMapper'a и в случае отмены просто перезаписать в текущий selecteditem созданный клон", но из-за того что автомапер создает полностью новый объект, этот объект судя по всему перестает отслеживаться моей ObservableCollection.

Вопросы:

  1. Как правильно делать отмену изменений ?
  2. Как померить automapper с EF?
Answer 1

Можно воспользоваться реализацией IEditableObject в классе модели

public class Person : INotifyPropertyChanged, IEditableObject
{
    //ссылка на экземпляр хранения предыд.значений на время редактирования
    private Person _tempValues;
    public event PropertyChangedEventHandler PropertyChanged;
    public int Id { get; set; }
    private int _OrderNumber;
    public int OrderNumber
    {
        get => _OrderNumber;
        set
        {
            _OrderNumber = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(OrderNumber)));
        }
    }

    private string _FirstName;
    public string FirstName
    {
        get => _FirstName;
        set
        {
            _FirstName = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FirstName)));
        }
    }
    private string _LastName;
    public string LastName
    {
        get => _LastName;
        set
        {
            _LastName = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(LastName)));
        }
    }
    #region Реализация IEditableObject
    /// <summary>
    /// Когда начинается редактирование
    /// </summary>
    public void BeginEdit()
    {
        _tempValues = new Person
        {
            Id = this.Id,
            OrderNumber = this.OrderNumber,
            FirstName = this.FirstName,
            LastName = this.LastName
        };
    }
    /// <summary>
    /// Когда редактирование завершено
    /// </summary>
    public void EndEdit()
    {
        _tempValues = null;
    }
    /// <summary>
    /// Когда редактирование отменяется
    /// </summary>
    public void CancelEdit()
    {
        if (_tempValues == null) return;
        this.Id = _tempValues.Id;
        this.OrderNumber = _tempValues.OrderNumber;
        this.FirstName = _tempValues.FirstName;
        this.LastName = _tempValues.LastName;
    } 
    #endregion
}

Например DataGrid что называется "из коробки" поддерживает вызов соотв.методов, и в частности вызывает CancelEdit() если во время редактирования ячейки нажать Esc. Ну, а в случае редактирования в текстбоксах можно поступить так

public class MainViewModel : IMainViewModel, INotifyPropertyChanged
{
    private readonly IPersonRepository _repo;
    private Person _selectedPerson;
    public event PropertyChangedEventHandler PropertyChanged;
    //ctor
    public MainViewModel(IPersonRepository repository)
    {
            _repo = repository ?? throw new ArgumentNullException(nameof(repository));
    }
    public async Task LoadData()
    {
        People = new ObservableCollection<Person>();
        var result = await _repo.GetPeopleOrderedByLastName();
        List<Person> people = result.ToList();
        for (int i = 0; i < people.Count; i++)
        {
            people[i].OrderNumber = i + 1;
            People.Add(people[i]);
        }
    }
    /// <summary>
    /// Коллекция для ListView
    /// </summary>
    public ObservableCollection<Person> People { get; private set; }

    /// <summary>
    /// Выделенный в ListView человек
    /// </summary>
    public Person SelectedPerson
    {
        get => _selectedPerson;
        set
        {
            //отменяем редактирование предыдущ.
            _selectedPerson?.CancelEdit();
            _selectedPerson = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedPerson)));
            //начинаем редактирование
            _selectedPerson?.BeginEdit();
        }
    }
    /// <summary>
    /// Кнопка Готово
    /// </summary>
    private ICommand _AddCommand;
    public ICommand AddCommand
    {
        get => _AddCommand = _AddCommand ?? new RelayCommand(OnAdd);
    }
    private async void OnAdd()
    {
        if (SelectedPerson == null) return;
        //заканчиваем редактирование
        SelectedPerson.EndEdit();
        //обновляем в БД
        await _repo.UpdatePerson(SelectedPerson);
        SelectedPerson = null;
        //перезагружаем список из БД
        await LoadData();
    }

    /// <summary>
    /// Кнопка Отмена
    /// </summary>
    private ICommand _CancelCommand;
    public ICommand CancelCommand
    {
        get => _CancelCommand = _CancelCommand ?? new RelayCommand(OnCancel);
    }
    private void OnCancel()
    {
        if (SelectedPerson == null) return;
        //отменяем редактирование
        SelectedPerson.CancelEdit();
    }
}

Весь пример можно посмотреть здесь.

READ ALSO
Данные из базы данных в txt файл

Данные из базы данных в txt файл

Всем привет! Есть веб приложение с базой студентов (id, Имя, возраст, сумма баллов) Хочу сделать выборку из базы 5 студентов с самыми высокими...

152
Локализация через ResX Resource Manager

Локализация через ResX Resource Manager

В ResX Resource Manager создал переводы всех строк (Neutral,en,ru,ru-RU)Git показал, что файлы добавились

122
Как selenium webdriver отлавливать реквесты с сайта

Как selenium webdriver отлавливать реквесты с сайта

может кто-то сталкивался с подобным тестированием и может помочь

158
Вывод 2у-мерного ассоциатвного массива Php

Вывод 2у-мерного ассоциатвного массива Php

Доброе время суток, некоторое время пытаюсь разобраться с ассоциативными массивами, искал информацию в интернете, но в силу моего кретинизма...

175