Обновление модели из модели вида
Обновить модель из модели вида
Я прочитал какой-то пост о MVVM, но я не уверен, что понимаю способ, которым модель представления обновляет модель
В настоящее время у меня есть два текстовых поля в пользовательском интерфейсе, которые привязаны к представлению XAML и вызывают модель представления при возникновении события . когда должно быть место в модели представления при обновлении модели?
Это модель вида
class ViewModel:INotifyPropertyChanged
{
private String _url;
private String _TemplateType;
public string URL
{
get { return _url; }
set
{
if (value != _url)
{
_url= value;
OnPropertyChanged("URL");
}
}
}
public string TemplateType
{
get { return _TemplateType; }
set
{
if (value != _TemplateType)
{
_TemplateType= value;
OnPropertyChanged("URL");
}
}
}
Модель
internal class DefineAddinModel
{
public string TemplateType { get; set; }
public String URL { get; set; }
}
4 ответа:
ViewModel обычно действует как оболочка вокруг модели и содержит ссылку на модель, которая может обновляться либо в ответ на команды, либо автоматически в установщиках свойств.
Обновление: Вот пример того, как виртуальная машина действует как оболочка вокруг модели. Это может показаться бесполезным в вашем примере, но вы обнаружите, что во многих случаях геттеры/сеттеры виртуальной машины должны выполнять какое-то преобразование значений, а не просто передавать их.
class ViewModel:INotifyPropertyChanged { private DefineAddinModel model; public string URL { get { return model.URL; } set { if (value != model.URL) { model.url = value; OnPropertyChanged("URL"); } } } public string TemplateType { get { return model.TemplateType; } set { if (value != model.TemplateType) { model.TemplateType = value; OnPropertyChanged("TemplateType"); } } }
Лучший способ обновить модель - это использовать событие, его безопаснее, поэтому выберите погоду с помощью нажатия кнопки или потерянного фокуса, или все, что вы хотите
void button_click(object sender,eventsarg e) { MyObj.URL = App.Locator.MyVM.MyDefineAddinModel.URL;// App.Locator because MVVMLight is tagged MyObj.TemplateType = App.Locator.MyVM.MyDefineAddinModel.TemplateType ; }
Но лично я использую следующие шаги:
1- в вашей ViewModel создайте объект
CurrentItem
типаDefineAddinModel
и без OnPropertyChanged затем свяжите его с представлением(UI) DataContext корневого элемента на представлении)2- для модели я использую INotifyPropertyChanged для каждого propery
3- после привязки datacontext вашего корневого элемента к CurrentItem вашего ViewModel затем привязать только
URL
иTemplateType
Свойства к элементам управления, так что любые изменения в текстовом поле обновит CurrentItem свойстваВы также можете выбрать тип привязки (on LostFocus, или OnPropertyChanged)
Вам нужно привязать текстовые поля к двум свойствам
URL
иTemplateType
. Попробуйте использоватьCommands
(вViewModel
)вместоevents
(в CodeBehind), так как вы находитесь вMVVM
. Для обновления модели: используйте кнопку с ее командным свойством, привязанным к OnSave, как в этом примере:private String _url; private String _TemplateType; private DefineAddinModel _defineAddin; public DefineAddinModel DefineAddin { get {return _defineAddin;} set { _defineAddin = value; OnPropertyChanged("DefineAddin"); } } public string URL { get { return _url; } set { if (value != _url) { _url= value; OnPropertyChanged("URL"); } } } public string TemplateType { get { return _TemplateType; } set { if (value != _TemplateType) { _TemplateType= value; OnPropertyChanged("URL"); } } } public RelayCommand OnSaved { get; set; } public ViewModel() { DefineAddin = new DefineAddinModel(); OnSaved = new RelayCommand(()=> { DefineAddin.URL = URL ; DefineAddin.TemplateType = TemplateType; });
Подумайте об использовании третьих лиц, таких как MVVMLight это очень помогает вам с MVVM и помощниками вокруг него (команды, Messenger, ViewModelLocator ...)
Я думаю, что правильный ответ здесь- "это зависит".
В большинстве общих случаев преимущество фактического использования ViewModel также заключается в отслеживании "переходного состояния", т. е. состояния операции "редактирование в процессе".
В этом конкретном случае вы бы Не отправляли свои изменения непосредственно в модель каждый раз, когда значение обновляется, вместо этого вы сделали бы это с помощью реализации ICommand 'Update', которая соберет все данные из ViewModel и отправит их вниз в модель. Модель.
Этот подход дает вам много преимуществ:
Пользователь представления может менять свое мнение столько раз, сколько захочет, и только тогда, когда он будет доволен, модель действительно обновится с их окончательным выбором
Вот пример того, как бы я это сделал.- это значительно снижает нагрузку на вашу службу сохраняемости, так как только окончательные изменения протолкнуты.
- это позволяет выполнять окончательную проверку на полном наборе значений, а не переходных состояниях, и, следовательно, сокращает Программирование сложность и накладные расходы.
- Это также делает ваш пользовательский интерфейс гораздо более гибким, так как все приведенные выше примеры подталкивают обновления на Диспетчер пользовательского интерфейса, и позволяет избежать необходимости обслуживать это с помощью задач или других асинхронных подходов.
Резервная модель никогда не находится в несогласованном состоянии, поскольку я бы предположил, что все значения в одном представлении/ViewModel связаны и имеют смысл только при обновлении вместе с использованием кислотного подхода.public class ViewModel:INotifyPropertyChanged { private String _url; private String _TemplateType; public ViewModel(){ UpdateCommand = new DelegateCommand(OnExecuteUpdate, OnCanExecuteUpdate); } public bool OnCanExecuteUpdate(object param){ // insert logic here to return true when one can update // or false when data is incomplete } public void OnExecuteUpdate(object param){ // insert logic here to update your model using data from the view model } public ICommand UpdateCommand { get; set;} public string URL{ get { return _url; } set { if (value != _url) { _url= value; OnPropertyChanged("URL"); } } } public string TemplateType { get { return _TemplateType; } set { if (value != _TemplateType) { _TemplateType= value; OnPropertyChanged("TemplateType"); } } } ... etc. } public class DelegateCommand : ICommand { Func<object, bool> canExecute; Action<object> executeAction; public DelegateCommand(Action<object> executeAction) : this(executeAction, null) {} public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute) { if (executeAction == null) { throw new ArgumentNullException("executeAction"); } this.executeAction = executeAction; this.canExecute = canExecute; } public bool CanExecute(object parameter) { bool result = true; Func<object, bool> canExecuteHandler = this.canExecute; if (canExecuteHandler != null) { result = canExecuteHandler(parameter); } return result; } public event EventHandler CanExecuteChanged; public void RaiseCanExecuteChanged() { EventHandler handler = this.CanExecuteChanged; if (handler != null) { handler(this, new EventArgs()); } } public void Execute(object parameter) { this.executeAction(parameter); } }