我正在 WinUI3 中编写 MVVM 应用程序,并且遇到了我不理解的行为。目前我的主视图有一个
NavigationView
控件。该控件包含一个 Frame
控件,该控件的 content 属性绑定到 ViewModel 中的属性。当用户单击 NavigationView
控件中的某个项目时,ViewModel 的 Content
属性将设置为适当的子 ViewModel,并且框架引用自定义数据模板选择器来决定要实例化哪个视图更新:
RootNavigationView.xaml:
<UserControl.DataContext>
<viewModel:RootNavigationViewModel />
</UserControl.DataContext>
<UserControl.Resources>
<local:CustomDataTemplateSelector x:Key="templateSelector"
MyViewTemplate="{StaticResource MyViewTemplate}"
--and some other DataTemplates are set here as properties/>
<DataTemplate x:Key="MyViewTemplate" x:DataType="viewModel:MyViewModel">
<local:MyView/>
</DataTemplate>
// other data templates go here
</UserControl.Resources>
<NavigationView>
<NavigationView.MenuItems>
...
</NavigationView.MenuItems>
<Frame Content="{Binding Content}"
ContentTemplateSelector="{StaticResource templateSelector}/>
</NavigationView>
奇怪的是,这不需要我在子视图中显式设置 DataContext,并且它们都实例化并显示到各自的 ViewModel 的零绑定错误。我的理解是,在每个视图中设置 DataContext 告诉它在实例化时实例化适当的 ViewModel 类,并绑定到该类的公开属性。如果没有这个显式设置,我不明白视图如何知道在哪里可以找到它的 DataContext?我知道 DataContext 是由子控件继承的,但对我来说,这意味着我的子视图应该将其 DataContext 设置为
RootNavigationViewModel
,而不是该类的 ViewModel 是什么。我什至收到有关无法找到 DataContext 的设计时警告,但在运行时仍然没有错误。它实际上比我以前更好,因为这样我就可以避免每次在视图之间切换时重新实例化我的 ViewModel,因此 ViewModel 数据在导航过程中得以保留!
我想知道我对数据绑定如何工作有什么误解,以至于我的代码仍然在这里运行。 DataTemplate 是否以某种方式将 DataContext 与视图通信?在这种情况下,为什么它的行为与在视图中显式指定 DataContext 不同?
由
DataTemplateSelector
(CustomDataTemplateSelector
) 创建的子视图接收 Frame
的 Content
作为 DataContext
。