Ken*_*Ken 2 data-binding prism mvvm
在另一篇文章(Prism BindableBase.SetProperty())中,@brian-lagunas 说他更喜欢将模型公开为属性并将视图绑定到模型属性。他给出了以下示例代码:
 public class MyViewModel : BindableBase
 {
     private Person _myPerson;
     public Person Person
     {
         get { return _myPerson; }
         set { SetProperty(ref _myPerson, value); }
     } 
 }
但是,我不确定如何绑定到属性。这会通知财产变化吗?
更新:这是我在模型上实现 INPC 的方式吗?如果是这样,通过将属性放在已经支持 INPC 的视图模型中,我获得了什么?
public class Person : INotifyPropertyChanged
{
    private string _FirstName;
    private string _LastName;
    public string FirstName { get { return _FirstName; } set => SetProperty(ref _FirstName, value); }
    public string LastName { get { return _LastName; } set => SetProperty(ref _LastName, value); }
    private void SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (!Equals(storage,value))
        {
            storage = value;
            OnPropertyChanged(propertyName);
        }
    }
    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged;
}
给定以下模型:
public class Person
{
   public string FirstName { get; set; }
}
绑定到FirstName属性,对 FirstName 的任何更新都不会有属性更改的通知。实现这一点的唯一方法是您的模型是否实现了INotifyPropertyChanged.
也就是说,直接绑定到模型可能是一个很好的策略。作为一个常见的例子,如果你有一个ListView,你通常可以ObservableCollection<SomeModel>安全地绑定到一个。如果您正在使用相对较小的数据集并且可以负担重新加载数据源的开销,那么您一直都很安全。
现在就如何绑定到属性而言,给出:
public class ViewAViewModel : BindableBase
{
    private Person _myPerson;
    public Person MyPerson
    {
        get { return _myPerson; }
        set { SetProperty( ref _myPerson, value ); }
    }
}
您的 XAML 标记如下所示:
<Label Text="{Binding MyPerson.FirstName}" />
更新:
正如您更新的问题中所述,是的,您可以这样实施INotifyPropertyChanged。请记住,它已经为您完成了,BindableBase因此鉴于您的示例,您可以简单地从BindableBase...继承...另一个不错的选择是,如果您使用James Montemagno 的MvvmHelpers,您可以ObservableObject在您的模型和BaseViewModel您的 ViewModel上使用他的,它为您提供标题、子标题等属性、图标、IsBusy、IsNotBusy。
这样做的好处当然是您现在可以直接绑定到模型。视图很少知道模型,请考虑以下事项:
人物模型
public class Person : BindableBase
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set { SetProperty( ref _firstName, value ); }
    }
    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set { SetProperty( ref _lastName, value ); }
    }
    private DateTime _dob;
    public DateTime DOB
    {
        get { return _dob; }
        set { SetProperty( ref _dob, value ); }
    }
}
用户个人资料视图模型
public class UserProfileViewModel : BindableBase, INavigationAware
{
    INavigationService _navigationService { get; }
    IPageDialogService _pageDialogService { get; }
    public UserProfileViewModel( INavigationService navigationService, IPageDialogService pageDialogService )
    {
        _navigationService = navigationService;
        _pageDialogService = pageDialogService;
        DoFooCommand = new DelegateCommand( () => _pageDialogService.DisplayAlertAsync( "Alert", "Foo", "Ok" ) );
    }
    private bool shouldSave = false;
    private string _title;
    public string Title
    {
        get { return _title; }
        set { SetProperty( ref _title, value ); }
    }
    private Person _user;
    public Person User
    {
        get { return _user; }
        set { SetProperty( ref _user, value ); }
    }
    public DelegateCommand DoFooCommand { get; }
    public void OnNavigatingTo( NavigationParameters parameters )
    {
        Title = AppResources.UserProfilePageTitle;
        User = parameters.GetValue<Person>( "currentUser" );
        User.PropertyChanged += ( sender, e ) => shouldSave = true;
    }
    public void OnNavigatedFrom( NavigationParameters parameters )
    {
        if( shouldSave )
        {
            // Do your persistence here.
        }
    }
    public void OnNavigatedTo( NavigationParameters parameters )
    {
        User.DOB = new DateTime( 2017, 1, 1 );
    }
}
用户个人资料视图
<ContentPage Title="{Binding Title}">
    <StackLayout>
        <Label Text="First Name" />
        <Entry Text="{Binding User.FirstName}" />
        <Label Text="Last Name" />
        <Entry Text="{Binding User.LastName}" />
        <Label Text="{Binding User.DOB}" />
        <Button Text="Do Foo" Command="{Binding DoFooCommand}" />
    </StackLayout>
</ContentPage>
鉴于此代码,应该有几点值得注意:
1) 我们的 ViewModel 由各种与我们的模型毫无关系的东西组成,比如命令,或者像标题这样的属性。它也有可能消费的各种服务,如INavigationService或IPageDialogService
2) 其次,我们可能想要限制用户可以编辑哪些属性以及 ViewModel 可以编辑哪些属性。
3)如果我们的模型实现了,INotifyPropertyChanged我们可以附加一个事件处理程序,让我们知道我们的模型在设置后发生了变化,以便我们可以保留这些变化。
4) 它使 XAML 对我们的意图更具可读性。我们没有绑定到一些名为 FirstName 的魔法属性。我们确实绑定到我们的 Person 模型的 FirstName 属性。
| 归档时间: | 
 | 
| 查看次数: | 1824 次 | 
| 最近记录: |