вы можете использовать один 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;
}));
Я предпочитаю второй способ. когда вы выполняете PropertyChange («SelectedPerson»), все «дочерние» привязки обновляются также как selectedperson.age, selectedperson.name. Его яснее, и вам не нужна куча «глупых» свойств «обертки». – Igor
Оба метода действительны. Первый - это более «пуристский» подход MVVM, и он лучше масштабируется в более крупных приложениях с несколькими разработчиками, а второй часто проще строить и обслуживать, поскольку нет дубликатов копий собственности. Поэтому просто выберите, какая из них лучше всего подходит для вас, и будьте последовательны в этом во всем своем приложении :) – Rachel