У меня есть головоломка с моим самым новым приложением.WPF MVVM с mvvmlight и Fluent.Validation
Это приложение MVFM WPF MVPM, которое использует MVVM Light и Fluent.Validation.
The View в DataContext является MainViewModel : ViewModelBase
с ObservableCollection<ProviderDto>
для ListView на левой и свойства ProviderDto SelectedProvider
для детальных свойств справа.
Есть также несколько RelayCommands
добавление, редактирование и удаление одиночных ProviderDto
«ы
ViewModel использует ProviderService
выполнить эти действия, которые впрыскивают в это конструктор с mvvmlight-х SimpleIoC
в отдельном ViewModelLocator
.
Все хорошо работает до сих пор, мне также удалось получить данные о времени разработки.
теперь я пытался добавить Fluent.Validation к Mix и реализован, как это описано в this post (My ProviderDto
Теперь наследуется от ValidationBase
вместо ObservableObject
. База Теперь наследуется от ObservableObject
. Также я зарегистрировал ProviderDtoValidator
в ViewModelLocator
.)
Это позволяет мне автоматически проверять мои ObservableObjects и называть .IsValid
.
Пока все хорошо, я уверен, что смогу заставить его работать до вида и сделать эти окна ошибок красными :).
Теперь мой вопрос:
Я хочу иметь кнопки на View, чтобы сохранить изменения на SelectedProvider
. Это, естественно, должны быть связаны с этим:
Relaycommand SaveProviderCommand = new RelayCommand(SaveProvider, CanSaveProvider)
private bool CanSaveProvider()
{
return SelectedProvider.IsValid;
}
private void SaveProvider()
{
if (SelectedProvider.IsValid)
_providerController.SaveProvider(SelectedProvider);
}
Где поставить SaveProviderCommand SaveCommand?
Если я положил его в ViewModel, то я могу назвать его из SelectedProvider-недвижимости:
public ProviderDto SelectedProvider
{
get { return _selectedProvider; }
set
{
Set(() => SelectedProvider, ref prV_selectedProvider, value);
SaveProviderCommand.RaiseCanExecuteChanged(); // Here!
}
}
который, очевидно, не работает, когда только одно свойство в SelectedProvider
получает изменилось.
Другая возможность заключается в том, чтобы поставить команду на сам DTO и вызвать ее каждый раз, когда свойство получает Изменено. Например, когда E-mail-Недвижимость меняется:
//A Property from Provider
public string Email
{
get { return _email; }
set
{
Set(() => Email, ref _email, value.TrimSafe());
SaveProviderCommand.RaiseCanExecuteChanged(); // Here!
}
}
Преимущество здесь в том, что проверка работает вне коробки до Вид-Level при изменении каждого свойства. Недостатком является то, что я должен был бы ввести ProviderController
в конструктор DTO, чтобы его можно было вызвать в частном Save-Method. Я не думаю, что DTO должен знать, как спасти себя. Он должен только определить, есть ли он .IsValid
, и логика сохранения должна принадлежать ViewModel.
Я надеюсь, что вы можете увидеть мою дилемму:
Если я поставил SaveCommand в ViewModel, то я должен буду делать I-Dont-знает-что, чтобы проверить мой SelectedProvider в представлении. Как будет работать валидация? Я посмотрел в DataTemplating Controls, но, похоже, я не могу заставить его работать вместе с Fluent.Validation ..
Если я поместил SaveCommand в сам DTO, то проверка работает хорошо, но я не думаю правильно вводить так много возможностей во что-то, что должно оставаться немым.
Конечно, это иллюстрированный пример, но я думаю, этого достаточно, чтобы проиллюстрировать проблему. Надеюсь получить хороший совет по шаблонам и практике.