2013-11-08 4 views
1

Допустим, у меня есть ListBox с несколькими объектами модели, позволяет называть его person с нормальными значениями, как name, age, familiyName и список объектов professions с произвольными значениями.MVVM привязки вид на сменной модели

Я хочу, чтобы теперь был создан элемент управления Inspector, который показывает значения выбранного объекта person, но мой квест.

Если модель просмотра Inspector имеет свои свойства (например, SelectedPersonName, SelectedPersonAge и т. Д.), Чтобы связать просмотр и обновить все их в случае изменения выбранного элемента в списке? Или я должен реализовать его, просто имея ссылку в viewmodel инспектора, ссылаясь на выбранный элемент в списке, заканчивая привязками, такими как {Binding SelectedPerson.name}{Binding SelectedPerson.age} Что лучше всего здесь? есть ли третий способ?

+1

Я предпочитаю второй способ. когда вы выполняете PropertyChange («SelectedPerson»), все «дочерние» привязки обновляются также как selectedperson.age, selectedperson.name. Его яснее, и вам не нужна куча «глупых» свойств «обертки». – Igor

+1

Оба метода действительны. Первый - это более «пуристский» подход MVVM, и он лучше масштабируется в более крупных приложениях с несколькими разработчиками, а второй часто проще строить и обслуживать, поскольку нет дубликатов копий собственности. Поэтому просто выберите, какая из них лучше всего подходит для вас, и будьте последовательны в этом во всем своем приложении :) – Rachel

ответ

2

Второй способ. Пока вы уведомляете, когда выбранный человек изменяется, и когда свойства этого человека меняются, все будет правильно связываться. И вам не нужно будет создавать новые свойства viewmodel.

1

вы можете использовать один ViewModel для каждой модели и инициализировать их в конструкторах, как это:

public class PersonVm : DependencyObject 
{ 
    public PersonVm(Model.Person model) 
    { 
     _model = model; 
     Name = model.Name; 
     Age = model.Age; 
     foreach (var professionModel in model.Professions) 
     { 
      Professions.Add(new ProfessionVm(professionModel)); 
     } 
    } 
    Model.Person _model; 
    public int Id { get { return _model.Id; } } 
    //Name Dependency Property 
    public string Name 
    { 
     get { return (string)GetValue(NameProperty); } 
     set { SetValue(NameProperty, value); } 
    } 
    public static readonly DependencyProperty NameProperty = 
     DependencyProperty.Register("Name", typeof(string), typeof(PersonVm), new UIPropertyMetadata(null)); 
    //Age Dependency Property 
    public int Age 
    { 
     get { return (int)GetValue(AgeProperty); } 
     set { SetValue(AgeProperty, value); } 
    } 
    public static readonly DependencyProperty AgeProperty = 
     DependencyProperty.Register("Age", typeof(int), typeof(PersonVm), new UIPropertyMetadata(0)); 

    //Professions Observable Collection 
    private ObservableCollection<ProfessionVm> _professions = new ObservableCollection<ProfessionVm>(); 
    public ObservableCollection<ProfessionVm> Professions { get { return _professions; } } 
} 

Это ViewModel для всей страницы или окна, вам нужно создать один экземпляр этого в конструкторе страницы или окна и установить DataContext к нему после InitializeComponent()

public class MainViewModel : DependencyObject 
{ 
    public MainViewModel(IEnumerable<Model.Person> models) 
    { 
     foreach (var personModel in models) 
     { 
      People.Add(new PersonVm(personModel)); 
     } 
    } 
    //People Observable Collection 
    private ObservableCollection<PersonVm> _people = new ObservableCollection<PersonVm>(); 
    public ObservableCollection<PersonVm> People { get { return _people; } } 

    //SelectedPerson Dependency Property 
    public PersonVm SelectedPerson 
    { 
     get { return (PersonVm)GetValue(SelectedPersonProperty); } 
     set { SetValue(SelectedPersonProperty, value); } 
    } 
    public static readonly DependencyProperty SelectedPersonProperty = 
     DependencyProperty.Register("SelectedPerson", typeof(PersonVm), typeof(MainViewModel), new UIPropertyMetadata(null)); 
} 

Таким образом, вы можете связать очень легко, как это:

<DockPanel> 
    <ListBox 
     DockPanel.Dock="Left" 
     ItemsSource="{Binding People}" 
     SelectedItem="{Binding SelectedPerson}" 
     DisplayMemberPath="Name"/> 
    <StackPanel DataContext="{Binding SelectedPerson}"> 
     <TextBlock Text="{Binding Name}"/> 
     <TextBlock Text="{Binding Age}"/> 
     <ListBox ItemsSource="{Binding Professions}" 
       DisplayMemberPath="Whatever"/> 
    </StackPanel> 
</DockPanel> 

Преимущество этого метода легко связывать. Также обновление модели осуществляется следующим образом:

//Name Dependency Property 
    public string Name 
    { 
     get { return (string)GetValue(NameProperty); } 
     set { SetValue(NameProperty, value); } 
    } 
    public static readonly DependencyProperty NameProperty = 
     DependencyProperty.Register("Name", typeof(string), typeof(PersonVm), 
     new UIPropertyMetadata(null, (d, e) => 
     { 
      var vm = (PersonVm)d; 
      var val = (string)e.NewValue; 
      vm._model.Name = val; 
     })); 
Смежные вопросы