在具有干净模型(未实现 INotifyPropertyChabged 之类的接口(interface))的 MVVM 应用程序中, View 模型包含绑定(bind)到 View 的属性,这些属性从 View 模型中包含的模型对象获取其值,并且应该在 View 更改时设置其属性的值绑定(bind)到这些属性的控件。
问题是 View 何时改变;更改由绑定(bind) View 模型属性捕获,但属性无法设置模型对象字段,模型不会更改。我需要模型字段接受 View 模型属性的设置,然后考虑到它是一个干净的模型,我可以将更新的模型保存到数据库中。
这里是 View 模型代码的一部分
public class SubsystemDetailsViewModel: INotifyPropertyChanged, ISubsystemDetailsViewModel
{
#region Fields
//Properties to which View is bound
private int? _serial;
public int? Serial
{
get { return Subsystem.Serial; }
set
{
//Subsystem.Serial=value;
_serial = value;
OnPropertyChanged("Serial");
}
}
private string _type;
public string Type
{
get { return Subsystem.Type; }
set
{
//Subsystem.Type = value;
_type = value;
OnPropertyChanged("Type");
}
}
//remaining properties ....
#endregion
//Service
private readonly ISubsystemService _subsystemService;
//Reference to the View
public ISubsystemDetailsView View { get; set; }
//Event Aggregator Event
private readonly IEventAggregator eventAggregator;
//Commands
public ICommand ShowTPGCommand { get; set; }
public DelegateCommand UpdateCommand { get; set; }
//
private bool _isDirty;
//Constructor ************************************************************************************************
public SubsystemDetailsViewModel(ISubsystemDetailsView View, ISubsystemService subsystemService, IEventAggregator eventAggregator)
{
_subsystemService = subsystemService;
this.View = View;
View.VM = this;
//EA-3
if (eventAggregator == null) throw new ArgumentNullException("eventAggregator");
this.eventAggregator = eventAggregator;
//Commands
this.ShowTPGCommand = new DelegateCommand<PreCommissioning.Model.Subsystem>(this.ShowTestPacks);
this.UpdateCommand = new DelegateCommand(this.UpdateSubsystem, CanUpdateSubsystem);
}
//****************************************************************************************************************
//ICommand-3 Event Handler
//this handler publish the Payload "SelectedSubsystem" for whoever subscribe to this event
private void ShowTestPacks(PreCommissioning.Model.Subsystem subsystem)
{
eventAggregator.GetEvent<ShowTestPacksEvent>().Publish(SelSubsystem);
}
//===============================================================================================
private void UpdateSubsystem()
{
_subsystemService.SaveChanges(Subsystem);
}
private bool CanUpdateSubsystem()
{
return _isDirty;
}
//*******************************************************************************************
public void SetSelectedSubsystem(PreCommissioning.Model.Subsystem subsystem)
{
this.SelSubsystem = subsystem;
}
//************************************************************************************************************
/// <summary>
/// Active subsystem >> the ItemSource for the View
/// </summary>
private PreCommissioning.Model.Subsystem _subsystem;
public PreCommissioning.Model.Subsystem Subsystem
{
get
{
//return this._subsystem;
GetSubsystem(SelSubsystem.SubsystemNo);
return this._subsystem;
}
set
{
if (_subsystem != value)
{
_subsystem = value;
OnPropertyChanged("Subsystem");
}
}
}
//Call the Service to get the Data form the Database
private void GetSubsystem(string SSNo)
{
this._subsystem = _subsystemService.GetSubsystem(SSNo);
}
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
_isDirty = true;
UpdateCommand.RaiseCanExecuteChanged();
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}
Subsystem 是使用 GetSubsystem() 方法填充的模型对象。像 Serial 这样的 View 模型属性从模型中获取其值,如图所示。我尝试设置模型属性,如属性设置部分中的注释行所示,但子系统对象没有发生变化,始终保持其原始值
最佳答案
如果 GetSubsystem
每次都返回一个新的子系统,那是你的问题。在您绑定(bind)到 View 的属性的“集合”中,您调用的是公共(public)属性“子系统”,而不是您创建的私有(private)字段。因此,每次从 View 中设置属性时,您都在调用 Subsystem.get,它调用 GetSubsystem(SelSubsystem.SubsystemNo);
.
我认为,在您的 ViewModel 属性中,您希望将其更改为:
//Properties to which View is bound
public int? Serial
{
get { return _subsystem.Serial; }
set
{
_subsystem.Serial=value; // NOTE THE USE OF THE PRIVATE FIELD RATHER THAN THE PROPERTY
OnPropertyChanged("Serial");
}
}
public string Type
{
get { return _subsystem.Type; }
set
{
_subsystem.Type = value; // NOTE THE USE OF THE PRIVATE FIELD RATHER THAN THE PROPERTY
OnPropertyChanged("Type");
}
关于MVVM : how to make view model set fields of clean model to persist view changes to database,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14162168/