如何在C# MVVM中绑定一对多关系

3
我一直在开发Windows表单应用程序,并初次使用MVVMLight Toolkit和WPF。
我的模型如下:
病人
Id, 名字, 姓氏, 等等...
测试结果
Id, 得分, 日期, 病人ID, 等等...
每个病人都可以有多个测试结果。在同一个视图(名为GTPView)上,我想显示一个病人列表框和一个测试结果列表框。当用户点击一个病人时,该病人的所有测试结果应出现在测试结果列表框中。
我知道如何将Patients ListBox的SelectedItem绑定到我的GTPViewModel中的Patient属性,但是如何将TestResults ListBox绑定到当前选定病人的所有TestResults?
我应该有一个TestResults ListBox的UserControl View和一个Patients ListBox的UserControl View,然后将这两个UserControls添加到我的GTPView中吗?还是最好只在一个视图中完成所有操作?
先谢谢你。如果需要更多信息,请告诉我。这是我的GTPView的XAML:
<Window x:Class="ApuntaNotas.Views.GTPView"            
        Title="GTP"            
        DataContext="{Binding GTP, Source={StaticResource Locator}}"
        d:DataContext="{d:DesignData /SampleData/PatientsViewModelSampleData.xaml}">
    <Window.Resources>
        <CollectionViewSource Source="{Binding Patients}" x:Key="PatientsVS">
            <CollectionViewSource.SortDescriptions>
                <ComponentModel:SortDescription PropertyName="Name" />
            </CollectionViewSource.SortDescriptions>
        </CollectionViewSource>
    </Window.Resources>
    <DockPanel>
        <ListBox DockPanel.Dock="Left" ItemsSource="{Binding Source={StaticResource PatientsVS}}"
                 x:Name="listBoxPatients" SelectedItem="{Binding SelectedPatient}" DataContext="{Binding}"
                 DisplayMemberPath="">
        </ListBox>
        <ListBox DockPanel.Dock="Right" ItemsSource="{Binding Source={StaticResource PatientsVS}}"
                 x:Name="listBoxTestResults"  DataContext="{Binding}"
                 DisplayMemberPath="">
        </ListBox>

    </DockPanel>
</Window>

2
通常情况下,您会像这样绑定测试结果列表框:<ListBox ItemsSource="{Binding SelectedItem.TestResults, ElementName=listBoxPatients}" />,如果您使用普通的视图模型。但我不知道这个 XML/Locator 的工作原理。此外,如果您不提供 XML 数据的示例,没有人能告诉您如何访问您的 XML 数据。 - 15ee8f99-57ff-4f92-890c-b56153
1个回答

5

您的PatientViewModel应该像这样

public class PatientViewModel: INotifyPropertyChanged
    {
       public int ID {get; set;}
       public string FirstName {get; set;}
       public string LastName {get; set;}
       //Each patient has a set of test results, so we create a list.
       public  List<TestResult> PatientTestResults {get; set;}
    }

您应该有一个额外的类来保存 PatientViewModel 的集合。
    public class AllPatients
    {
        public ObservableCollection<PatientViewModel> AllPatients{get; set;}
        public PatientViewModel SelectedPatient {get; set;}
    }

您的Window类现在应该看起来像这样:
  <ListBox x:Name="listBoxPatients" 
           ItemsSource="{Binding  AllPatients}"
           SelectedItem="{Binding SelectedPatient}"
           IsSynchronizedWithCurrentItem="True"/>

  <ListBox x:Name="listBoxTestResults"
           ItemsSource="{Binding SelectedPatient.TestResults}"
           IsSynchronizedWithCurrentItem="True"/>                 

1
我认为你想要在第二个ListBox的ItemsSource绑定中摆脱ElementName=listBoxPatients,因为它现在被绑定到视图模型(SelectedPatient)的属性上,而不是另一个listbox上的SelectedItem - 15ee8f99-57ff-4f92-890c-b56153
1
是的,你说得对,已经相应地更新了代码。谢谢。 - Marshal
我正在做类似的事情。如果不使用可观察的集合,你怎么可能在列表框中显示PatientTestResults呢? - Travis Tubbs
1
@TravisTubbs:PatientTestResults已经是一个列表,而Patient的集合是ObservableCollection。一般来说,如果集合会被修改并且需要CollectionChanged通知,则通常使用ObservableCollection。如果您认为您的患者数量将保持不变,或者如果您有其他接收列表更改通知的方法,则甚至可以使用IEnumerable。 - Marshal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接