从视图模型
更新模型我已经阅读了一些关于MVVM的帖子,但我不确定是否理解 视图模型更新模型的方式
目前,我在UI中有两个文本框,它们绑定到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; }
}
答案 0 :(得分:5)
ViewModel通常充当模型的包装器,并包含对Model的引用,该引用可以响应命令更新,也可以在属性设置器中自动更新。
更新: 这是一个让VM充当模型包装器的例子。在您的示例中,这似乎无用,但在很多情况下,您会发现VM的getter / setter需要对值进行某种转换,而不是简单地传递它们。
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");
}
}
}
答案 1 :(得分:1)
更新模型的更好方法是使用一个事件,它更安全,所以选择天气使用按钮点击或失去焦点,或任何你想要的
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 ;
}
但是personnaly我使用以下步骤:
1 - 在ViewModel中创建CurrentItem
类型为DefineAddinModel
的对象,而不使用OnPropertyChanged,然后将其绑定到View上RootElement的View(UI)DataContext
2 - 我为每个属性使用INotifyPropertyChanged
将根元素的datacontext绑定到ViewModel的CurrentItem之后 3 - 然后只将URL
和TemplateType
属性绑定到您的控件,所以任何事情都会改变文本框将更新CurrentItem属性
你也可以选择绑定的类型(On LostFocus,或OnPropertyChanged)
答案 2 :(得分:1)
您需要将TextBox绑定到两个属性URL
和TemplateType
。
因为您在Commands
,所以请尝试使用ViewModel
(在events
)而不是MVVM
(在CodeBehind中)。
要更新模型:使用一个按钮,将其Command属性绑定到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及其周围的助手(Commands,Messenger,ViewModelLocator ......)
答案 3 :(得分:1)
我认为这里的正确答案是'它取决于'。
在大多数情况下,实际使用ViewModel的优势还在于跟踪“瞬态”,即“正在编辑”操作的状态。
在这种特殊情况下,每次更新值时,不都会直接将更改推送到模型,而是通过“更新”ICommand实现来执行此操作,该实现将收集所有数据从ViewModel中将其推送到Model。
这种方法为您提供了许多优势:
这是我如何做的一个例子。
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);
}
}