您当然可以让您的主视图(基板 .xaml 文件,如您在上面描述的那样)没有DataContext
然后分配DataContext
特定子控件,无论它们是否UserControls
。
但是,根据您的描述,您可能需要考虑将 Composition 与您的 ViewModel 一起使用。在这种情况下,您将拥有一个 MainViewModel,它具有表示 ChildViewModel(技术人员和测试)的属性。这些子 ViewModel 可以通过 MainViewModel 进行通信,也可以不通过 MainViewModel 进行通信,具体取决于您想要如何组合。然后,DataContext
主视图的 将是 MainViewModel,而UserControls
将只是DataBind
该视图模型的属性。
它可能看起来像这样:
public class MainViewModel : BaseViewModel
{
public TechnicianViewModel Technician { get { return _technician; } }
public TestViewModel Test { get { return _test; } }
...
}
XAML 的缩写示例如下所示(假设 MainViewModel 已设置为 Window 的 DataContext):
<Window x:Class="MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<local:TechnicianView DataContext="{Binding Technician}"/>
<local:TestView DataContext="{Binding Test}"/>
</StackPanel>
</Window>
这就是我解决上述场景类型的方法,并且效果很好。当您可以使用 IoC/DI 通过 IoC 容器注入子视图模型时,它工作得很好。
已编辑
根据您在下面的评论/问题,一些额外的细节。您询问如何在选定的技术人员和该技术人员可用的测试之间建立关系。处理此问题的一种方法是让 TestsViewModel 成为 TechnicanViewModel 的子项。因此,例如,您可以拥有以下内容:
public class MainViewModel : BaseViewModel
{
public IEnumerable<TechnicianViewModel> AvailableTechnicians { get { return _technicians; } }
public TechnicianViewModel SelectedTechnician
{
get { return _selected; }
set
{
_selected = value;
RaiseNotifyPropertyChanged("SelectedTechnician");
}
}
...
}
public class TechnicianViewModel : BaseViewModel
{
public IEnumerable<TestViewModel> Tests { get { return _tests; } }
}
然后在您的 XAML 中:
<StackPanel>
<ListBox ItemsSource="{Binding AvailableTechnicians}" SelectedItem="{Binding SelectedTechnician, Mode=TwoWay}"/>
<ListBox ItemsSource="{Binding SelectedTechnician.Tests}"/>
</StackPanel>
这将使测试ListBox
与技术人员中选定的技术人员同步ListBox
。这只是一个示例(在文本编辑器中编写,如果我有任何错误,则不是 VS),而是处理您正在讨论的那种关系的一种方法。