2017-03-09 106 views
0

在另一篇文章(Prism BindableBase.SetProperty())上,@ brian-lagunas說他更喜歡將Model作爲屬性公開,並將View綁定到模型屬性。他給出了以下示例代碼:綁定到屬性更改模型

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; 
} 

回答

2

考慮以下模型:

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)我們的視圖模型包含什麼都沒有做什麼那麼我們的模型像命令,或類似的標題性質的各種事情。它也有可能消費的各種服務,如INavigationServiceIPageDialogService

2)其次,我們可能要限制哪些屬性的用戶可以編輯和視圖模型可以編輯。 3)如果我們的模型實現了INotifyPropertyChanged,我們可以附加一個事件處理程序,讓我們知道我們的模型在設置後發生了變化,因此我們可以保留這些更改。

4)它使XAML更具可讀性瞭解我們的意圖。我們不綁定一些名爲FirstName的魔術屬性。我們真的綁定了我們的Person模型的FirstName屬性。

+0

我已更新我的問題以添加INPC的實現。通過在已經實現INPC的視圖模型中擁有屬性,我獲得了什麼? – Ken

+0

它變得更清晰。感謝你和我一起在那裏。在你的視圖模型中,你有一個帶有後臺字段的用戶屬性。那完成了什麼?爲什麼不只是有一個自動實施的財產? – Ken

+0

從技術上講,它不應該需要它,因爲模型實現了'INotifyPropertyChanged',但是我傾向於按照約定來做所有事情,除了一個'ObservableCollection'或其他明確命名爲'Observable'的自定義Observable Type。它確保更好的代碼可讀性。 –

0

我不確定我是如何綁定到屬性。

要綁定到模型的屬性,你必須將數據綁定到屬性暴露模型及其財產,也就是說,如果你已經暴露的財產「人」 你的模型,並要綁定到的人的名稱屬性, '不需要綁定'Person.Name'。

這是否通知財產變化?

https://msdn.microsoft.com/en-us/library/dn736263(v=pandp.50).aspx

SetProperty方法將通知屬性更改的照顧。

+0

我明白的SetProperty將處理通知,但布賴恩的模式,而不是屬性使用的SetProperty。如果財產發生變化,通知是否會被髮送? – Ken

+0

是的,但它會是你的模型,誰就會發送屬性更改通知,並作爲後提到,你的模型需要實現通過曝光模式爲屬性INPC –

+0

那麼我該怎麼獲得? SetProperty調用對模型有什麼影響? – Ken