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