考慮以下模型:
public class Person
{
public string FirstName { get; set; }
}
綁定到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}" />
UPDATE:
如文獻你的更新問題,是的,你可以實現這樣的INotifyPropertyChanged
。記住它已經做了你BindableBase
所以給你的例子,你可以簡單地從BindableBase
繼承...另一個很好的選擇是,如果你使用MvvmHelpers從詹姆斯Montemagno你可以用他ObservableObject
您的模型和BaseViewModel
爲您的ViewModels,讓你的屬性如Title,SubTitle,Icon,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)我們的視圖模型包含什麼都沒有做什麼那麼我們的模型像命令,或類似的標題性質的各種事情。它也有可能消費的各種服務,如INavigationService
或IPageDialogService
2)其次,我們可能要限制哪些屬性的用戶可以編輯和視圖模型可以編輯。 3)如果我們的模型實現了INotifyPropertyChanged
,我們可以附加一個事件處理程序,讓我們知道我們的模型在設置後發生了變化,因此我們可以保留這些更改。
4)它使XAML更具可讀性瞭解我們的意圖。我們不綁定一些名爲FirstName的魔術屬性。我們真的綁定了我們的Person模型的FirstName屬性。
我已更新我的問題以添加INPC的實現。通過在已經實現INPC的視圖模型中擁有屬性,我獲得了什麼? – Ken
它變得更清晰。感謝你和我一起在那裏。在你的視圖模型中,你有一個帶有後臺字段的用戶屬性。那完成了什麼?爲什麼不只是有一個自動實施的財產? – Ken
從技術上講,它不應該需要它,因爲模型實現了'INotifyPropertyChanged',但是我傾向於按照約定來做所有事情,除了一個'ObservableCollection'或其他明確命名爲'Observable'的自定義Observable Type。它確保更好的代碼可讀性。 –