1

假设我有一个ListBox具有多个模型对象的模型,让我们person用正常值(如name, age)和具有任意值familiyName的对象列表来调用它。professions

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

Inspector 视图模型是否应该有自己的属性(例如SelectedPersonNameSelectedPersonAge)来绑定视图,并在列表框中的选定项目发生更改时更新所有这些属性?或者我应该通过简单地在检查器视图模型中引用列表框中的所选项目来实现它,最终得到像{Binding SelectedPerson.name} {Binding SelectedPerson.age}这里的最佳实践是什么?有第三种方法吗?

4

2 回答 2

2

第二种方式。只要您通知所选人员何时更改,以及该人的属性更改时,它都会正确绑定。而且您不需要创建一堆新的视图模型属性。

于 2013-11-08T18:20:09.053 回答
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,您需要在页面或窗口的构造函数中创建它的一个实例,并在InitializeComponent()之后将DataContext设置为它

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;
        }));
于 2013-11-08T18:30:13.087 回答