C# 从视图模型更新模型

C# 从视图模型更新模型,c#,wpf,mvvm,mvvm-light,C#,Wpf,Mvvm,Mvvm Light,从视图模型更新模型 我读过一些关于MVVM的帖子,但我不确定是否理解 视图模型更新模型的方式 目前,我在UI中有两个文本框,它们绑定到XAML视图,并在引发事件时调用视图模型。 更新模型时,视图模型中的位置应在何时 这是视图模型 class ViewModel:INotifyPropertyChanged { private String _url; private String _TemplateType; public string URL { get

从视图模型更新模型

我读过一些关于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; }
}

ViewModel通常充当模型的包装器,包含对模型的引用,该模型可以响应命令或在属性设置器中自动更新

更新: 下面是一个让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");
            }
        }
    }

更新模型的更好方法是使用事件,因为它更安全,所以请使用按钮单击或失去焦点选择天气,或者任何您想要的方式

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-在视图模型中创建类型为
DefineAddinModel
且未更改OnPropertyChanged的
CurrentItem
对象,然后将其绑定到视图上根元素的视图(UI)数据上下文)

2-对于模型,我为每个属性使用InotifyProperty更改

3-将根元素的datacontext绑定到ViewModel的CurrentItem后,只需将
URL
TemplateType
属性绑定到控件,因此文本框上的任何更改都将更新CurrentItem属性


您还可以选择绑定类型(在LostFocus或OnPropertyChanged上)

您需要将文本框绑定到两个属性
URL
TemplateType
。 尝试使用
命令
(在
视图模型中
)而不是
事件
(在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;
                              });

考虑使用第三方,比如它对MVVM及其周围的助手(命令、Messenger、ViewModelLocator…)有很大帮助。我认为正确的答案是“视情况而定”

在大多数情况下,实际使用ViewModel的优势还在于跟踪“瞬态”,即“正在编辑”操作的状态

在这种特殊情况下,您不会在每次更新值时直接将更改推送到模型上,而是通过“更新”ICommand实现,该实现将从ViewModel收集所有数据并将其下推到模型上

这种方法有很多优点:

  • 视图的用户可以随时改变主意,只有当他们满意时,模型才会真正得到更新,并有明确的选择
  • 它极大地降低了持久性服务的负载,因为只有最后的更改才被推送通过
  • 它允许您对一组完整的值(而不是瞬态)进行最终验证,从而降低编程复杂性和开销
  • 它还使您的UI更加流畅,因为上面的所有示例都在UI Dispatcher上推送更新,并且避免了您必须通过任务或其他异步方法来满足这一需求
  • 支持模型永远不会处于不一致的状态,因为我可以想象一个视图/视图模型上的所有值都是相关的,并且只有在使用ACID方法一起更新时才有意义
  • 下面是一个我会如何做的例子

    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);
        }
    }
    
    公共类视图模型:INotifyPropertyChanged{
    私有字符串url;
    私有字符串_TemplateType;
    公共视图模型(){
    UpdateCommand=newdelegateCommand(OnExecuteUpdate、OnCanExecuteUpdate);
    }
    公共bool OnCanExecuteUpdate(对象参数){
    //在此处插入逻辑,以便在可以更新时返回true
    //或当数据不完整时为false
    }
    public void OnExecuteUpdate(对象参数){
    //在此处插入逻辑以使用视图模型中的数据更新模型
    }
    公共ICommand UpdateCommand{get;set;}
    公共字符串URL{
    获取{return\u url;}
    设置{
    如果(值!=\u url){
    _url=值;
    OnPropertyChanged(“URL”);
    }
    }
    }
    公共字符串模板类型{
    获取{return\u TemplateType;}
    设置{
    如果(值!=\u模板类型){
    _TemplateType=值;
    OnPropertyChanged(“模板类型”);
    }
    }
    }
    等
    }
    公共类DelegateCommand:ICommand{
    Func canExecute;
    行动执行;
    公共DelegateCommand(操作执行)
    :this(executeAction,null){}
    公共DelegateCommand(操作执行,函数canExecute){
    if(executeAction==null){
    抛出新ArgumentNullException(“executeAction”);
    }
    this.executeAction=executeAction;
    this.canExecute=canExecute;
    }
    公共布尔CanExecute(对象参数){
    布尔结果=真;
    Func canExecuteHandler=this.canExecute;
    如果(canExecuteHandler!=null){
    结果=canExecuteHandler(参数);
    }
    返回结果;
    }
    公共事件处理程序CanExecuteChanged;
    public void raisecancecutechanged(){
    EventHandler=this.CanExecuteChanged;
    if(处理程序!=null){
    处理程序(这是新的EventArgs());
    }
    }
    public void Execute(对象参数){
    此.executeAction(参数);
    }
    }
    
    您应该更新一些操作,如保存。请提供示例,提前感谢!谢谢,您在哪里实例化模型?@S