绑定到 属性 更改的模型
Binding to the model for property changes
在另一个 post (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;
}
I'm unsure how I'm to bind to the properties.
要绑定到模型的属性,您必须将数据绑定到公开模型及其 属性 的 属性,即如果您使用 属性 'Person' 公开了模型]
并且想要绑定到 Name 属性 of person,你不需要绑定到 'Person.Name'.
Does this notify of property changes?
https://msdn.microsoft.com/en-us/library/dn736263(v=pandp.50).aspx
SetProperty 方法将负责通知 属性 更改。
给定以下模型:
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 属性.
在另一个 post (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;
}
I'm unsure how I'm to bind to the properties.
要绑定到模型的属性,您必须将数据绑定到公开模型及其 属性 的 属性,即如果您使用 属性 'Person' 公开了模型] 并且想要绑定到 Name 属性 of person,你不需要绑定到 'Person.Name'.
Does this notify of property changes?
https://msdn.microsoft.com/en-us/library/dn736263(v=pandp.50).aspx
SetProperty 方法将负责通知 属性 更改。
给定以下模型:
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 属性.