C# 从视图模型更新模型
从视图模型更新模型 我读过一些关于MVVM的帖子,但我不确定是否理解 视图模型更新模型的方式 目前,我在UI中有两个文本框,它们绑定到XAML视图,并在引发事件时调用视图模型。 更新模型时,视图模型中的位置应在何时 这是视图模型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
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收集所有数据并将其下推到模型上 这种方法有很多优点:
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