Обзор
Я использую CompositeWPF для создания приложения на C #. Это действительно должно изменить ситуацию к ответу, так как моя проблема будет существовать вне Призмы.
У меня есть ItemsControl, который связан с ObservableCollection, содержащей мои ViewModels. Это работает нормально. В моем DataTemplate мои обязательные элементы управления связаны в XAML. Одним из таких элементов управления является кнопка «Конфигурировать». При нажатии на кнопку выдается DelegateCommand, который передает ViewModel в качестве параметра.
DelegateCommand открывает модальное диалоговое окно, показывающее, что виртуальная машина выглядит следующим образом.
private void ShowDialog(object obj)
{
ComPortPropertiesPresenter presenter = _container.Resolve<ComPortPropertiesPresenter>();
ComPortViewModel vm = obj as ComPortViewModel;
presenter.ComPort = vm.Clone() as ComPortViewModel;
DialogOptions options = new DialogOptions();
options.DialogTitle = presenter.View.DisplayName;
options.HideOkCancelButtons = true;
bool? result = DialogWorkspace.ShowView(presenter.View, options, () =>
{
return true;
});
if (result == true)
{
// TODO: There must be a better way of doing this. The problem is if you bind the object the
// automated bindings cause a realtime update. If you clone the object and then set it to become obj then
// the bindings do not update. Need to investigate how an observablecollection triggers an update.
int position = ComPorts.IndexOf(obj as ComPortViewModel);
ComPorts.Remove(obj as ComPortViewModel);
ComPorts.Insert(position, presenter.ComPort);
}
Мой оригинальный код передал объект ведущему без клона. Проблема в том, что значение менялось в реальном времени. Если вы внесли изменение, а затем нажали «Отмена», диалоговое окно было бы закрыто, хотя из-за привязок изменения уже произошли.
Я решил клонировать виртуальную машину и передать ее в представление. Если результат диалога был равен true, я попытался скопировать клонированный vm поверх оригинала. Например: obj = Presenter.ComPort;
Это не обновляло значения в исходном представлении, которое содержало кнопку.
Затем я попробовал что-то вроде ... obj.BaudRate = Presenter.ComPort.BaudRate, которое сработало, хотя я боюсь, что оно слишком затянуто, и если виртуальная машина будет расширена, то что-то может пропустить.
Мое окончательное решение состояло в том, чтобы удалить оригинальный vm и добавить новый в местоположение оригинала. Это работает на 100%, хотя я чувствую, что это немного неуклюже. Я чересчур критичен или есть лучший способ?
Я предполагаю, что ObservableCollection запускает событие INotify, когда что-то добавляется / удаляется. То же самое в моем vm, когда свойство обновляется, оно работает, потому что я вызываю событие.
Так может ли быть проблема в том, что если вы перезаписываете что-то в ObservableCollection, событие не генерируется?
Должны быть какие-то умные засорения, которые знают.