MVVM绑定视图到可更改的模型

时间:2013-11-08 18:14:41

标签: c# wpf mvvm

假设我有一个包含多个模型对象的ListBox,我们可以使用personnameage等正常值称呼familiyName具有任意值的对象列表professions

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

Inspector视图模型是否应具有自己的属性(如SelectedPersonNameSelectedPersonAge等...)以将视图绑定到,并在列表框中所选项更改的情况下更新所有属性?或者我应该通过在检查器视图模型中引用列表框中所选项目的引用来实现它,最后是{Binding SelectedPerson.name} {Binding SelectedPerson.age}这样的绑定。这里的最佳做法是什么?还有第三种方式吗?

2 个答案:

答案 0 :(得分:2)

第二种方式。只要您在所选人员更改时通知,并且当该人员的属性发生更改时,它们都将正确绑定。而且您不需要创建一堆新的viewmodel属性。

答案 1 :(得分: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;
        }));
相关问题