У меня есть проект для моего колледжа. В нем я пытаюсь реализовать MVVM + WPF + EF6. По ходу возникла проблема, которую я не могу решить уже слишком долго.
Немного о том что я уже смог сделать:
Есть класс MedRecordViewModel - view model с свойством selecteditem и определёнными CRUD командами, есть view MedRecordEdit в которую передаётся в качестве datacontexts'a - MedRecordViewModel.
Суть проблемы: Я не могу сделать отмену изменений, которые сразу же применяются из-за реализованного inotifypropertychanged интерфейса.
Я нашел решение по типу "создать клон объекта с помощью AutoMapper'a и в случае отмены просто перезаписать в текущий selecteditem созданный клон", но из-за того что автомапер создает полностью новый объект, этот объект судя по всему перестает отслеживаться моей ObservableCollection.
Вопросы:
Можно воспользоваться реализацией 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();
}
}
Весь пример можно посмотреть здесь.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Всем привет! Есть веб приложение с базой студентов (id, Имя, возраст, сумма баллов) Хочу сделать выборку из базы 5 студентов с самыми высокими...
В ResX Resource Manager создал переводы всех строк (Neutral,en,ru,ru-RU)Git показал, что файлы добавились
может кто-то сталкивался с подобным тестированием и может помочь
Доброе время суток, некоторое время пытаюсь разобраться с ассоциативными массивами, искал информацию в интернете, но в силу моего кретинизма...