从模型更新ViewModel中属性的正确方法 [英] Correct way to update property in ViewModel from Model

查看:240
本文介绍了从模型更新ViewModel中属性的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是WPF的新手.据我了解,数据会在模型中发生变化,并且应该通知视图模型,并且视图将绑定到视图模型中的属性和类似内容.这样对吗?如果是这样,我一直在阅读该模型应该实现INotifyPropertyChanged,并且看起来像这样

I'm fairly novice with WPF. It's my understanding that data changes in the model, and it should notify the viewmodel, and the view will bind to properties and things alike in the viewmodel. Is this correct? If so, I've been reading that the model should implement INotifyPropertyChanged, and look something like this

 public class LoginModel : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    }

    public bool Authenticated { get; set; }
}

在我的ViewModel中,我有一个属性"AuthResult",应该从Model属性"Authenticated"中获取更新

and in my ViewModel, I have a property "AuthResult", that should get the update from the Model property "Authenticated"

public partial class view1 : UserControl, INotifyPropertyChanged{
 public bool AuthResult
    {
        get
        {
            return _authVal;
        }
        set
        {
            _authVal = value;
            NotifyPropertyChanged("AuthResult");
        }
    }

public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    }
}

我知道这个当前的实现是不正确的.我发现我应该从我的模型中订阅PropertyChanged通知,如下所示:

I know this current implementation is incorrect. I've found that I should be subscribing to the PropertyChanged notification from my model like so:

    LoginModel.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(LoginModel_PropertyChanged);

void LoginModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    if(e.PropertyName == "Authenticated")
    {
         //do something
    }
}

我看不到"AuthResult"属性应在何处更新.我是否可以在If语句中做类似AuthResult = _model.Authenticated;的事情?

I don't see where the "AuthResult" property should be updated. Would I do something in the If statement like AuthResult = _model.Authenticated;?

在我的构造函数中?

LoginModel _model;

        public view1(LoginModel model)
        {
            _model = model;
            InitializeComponent();           
        }

推荐答案

如果模型实现了INotifyPropertyChanged接口,则可以从视图直接将其绑定:

If the model implements the INotifyPropertyChanged interface you can bind directly to it from the view:

<Button Content="Button" IsEnabled="{Binding Authenticated}" />

请注意,每当Authenticated属性设置为新值时,LoginModel类都必须引发PropertyChanged事件.

Note that the LoginModel class must raise the PropertyChanged event whenever the Authenticated property is set to a new value.

您还可以通过视图模型类公开整个模型实体:

You could also expose the entire model entity through the view model class:

public class ViewModel
{
    public ViewModel(LoginModel model)
    {
        Model = model;
    }

    public LoginModel Model { get; }
}

...并像这样绑定到它:

...and bind to it like this:

<Button Content="Button" IsEnabled="{Binding Model.Authenticated}" />

仍然是模型类,必须实现INotifyPropertyChanged接口并引发更改通知.

It is still the model class that must implement the INotifyPropertyChanged interface and raise change notifications.

视图模型的另一个选项是包装您希望能够从视图绑定到的模型类的任何属性.然后,绑定到视图模型类的属性,该属性又将模型类的属性包装如下:

Another option is for the view model to wrap any property of the model class that you want to be able to bind to from the view. Then you bind to a property of the view model class that in turn wraps a property of the model class something like this:

public class ViewModel
{
    private readonly LoginModel _model;
    public ViewModel(LoginModel model)
    {
        _model = model;
    }

    public bool AuthResult
    {
        get
        {
            return _model.Authenticated;
        }
        set
        {
            _model.Authenticated = value;
            NotifyPropertyChanged("AuthResult");
        }
    }
}

<Button Content="Button" IsEnabled="{Binding AuthResult}" />

使用后一种方法的好处是视图不依赖于模型类.它仅绑定到视图模型类,这通常就是实现MVVM设计模式的方式.

The benefit of using this latter approach is that view has no dependency upon the model class. It binds to the view model class only and this is how the MVVM design pattern typically is meant to be implemented.

但是,如果您确实绑定到视图模型的(包装器)属性,并且希望在设置模型类的属性时更新视图,则该模型必须通知视图模型它已以一种方式更改或另一个,即它必须引发某种事件或类似事件.这通常意味着实现INotifyPropertyChanged接口.然后,无论何时更新模型,视图模型都可以订阅模型的PropertyChanged事件,并为数据绑定属性引发其自己的PropertyChanged事件,例如:

But if you do bind to a (wrapper) property of the view model and want the view to be updated whenever a property of the model class is set, the model has to notify the view model that it has changed one way or another, i.e. it has to raise some kind of event or similar. And this typically means implementing the INotifyPropertyChanged interface. The view model can then subscribe to the PropertyChanged event of the model and raise its own PropertyChanged event for the data bound property whenever the model is updated, e.g.:

public class ViewModel
{
    private readonly LoginModel _model;

    public ViewModel(LoginModel model)
    {
        if (model == null)
            throw new ArgumentNullException("model");

        _model = model;
        _model.PropertyChanged += OnModelChanged;
    }

    private void OnModelChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Authenticated")
            NotifyPropertyChanged("AuthResult");
    }

    public bool AuthResult
    {
        get
        {
            return _model.Authenticated;
        }
        set
        {
            _model.Authenticated = value;
            NotifyPropertyChanged("AuthResult");
        }
    }
}

这篇关于从模型更新ViewModel中属性的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆