C# MVVM将视图绑定到可变模型

C# MVVM将视图绑定到可变模型,c#,wpf,mvvm,C#,Wpf,Mvvm,假设我有一个包含多个模型对象的列表框,我们用正常值称它为person,比如name、age、familyName和一个包含任意值的对象列表 我现在想创建一个Inspector控件,它显示所选person对象的值,但我的任务是 Inspector viewmodel是否应该有自己的属性(如SelectedPersonName,SelectedPersonAge等)来绑定视图,并在列表框中的选定项发生更改时更新所有属性?或者,我应该通过在inspector viewmodel中引用列表框中的选定项来

假设我有一个包含多个模型对象的
列表框
,我们用正常值称它为
person
,比如
name
age
familyName
和一个包含任意值的对象列表

我现在想创建一个Inspector控件,它显示所选
person
对象的值,但我的任务是


Inspector viewmodel是否应该有自己的属性(如
SelectedPersonName
SelectedPersonAge
等)来绑定视图,并在列表框中的选定项发生更改时更新所有属性?或者,我应该通过在inspector viewmodel中引用列表框中的选定项来实现它,最终使用像
{Binding SelectedPerson.name}
{Binding SelectedPerson.age}
这样的绑定来实现它吗?有第三条路吗?第二条路。只要您在所选人员发生更改时发出通知,以及该人员的属性发生更改时发出通知,所有这些都将正确绑定。您不需要创建一组新的viewmodel属性。

您可以为每个模型使用一个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; } }
}
<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>

我喜欢第二条路。当您执行PropertyChange(“SelectedPerson”)时,所有“子”绑定也会像SelectedPerson.age、SelectedPerson.name一样刷新。它更清晰,而且您不需要一堆“愚蠢的”“包装器”属性这两种方法都是有效的。第一种是更多的“MVVM纯粹主义”方法,在具有多个开发人员的大型应用程序中可以更好地扩展,而第二种方法通常更易于构建和维护,因为没有重复的属性副本。因此,只需选择最适合您的,并在整个应用程序中保持一致:)
<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;
        }));