我最近一直在尝试WPF,Xaml,MVVM和DependencyInjection。因此,我正在使用MVVM原则创建UI。 UI的某个部分被设计成像向导一样,其中并非所有可用选项同时呈现给用户。每个选项部分都是自己的视图(子视图),其中一个视图(父视图)在ContentControl中托管这些子视图。用户设置某些选项并使用按钮从一个部分移动到另一个部分。
查看导航
要在这些视图之间切换,我正在使用DataTemplateSelector,每个子视图在我的Xaml资源中定义为DataTemplate。
主视图中的内容控制:
<ContentControl Content="{Binding ElementName=ParentViewControl, Path=ViewState, Mode=TwoWay}"
ContentTemplateSelector="{StaticResource MyTemplateSelector}" />
示例子视图数据模板:
<DataTemplate x:Key="SubViewATemplate">
<local:SubViewAView x:Name="SVAView" DataContext="{Binding ElementName=ParentViewControl, Path=DataContext}" ViewState="{Binding ElementName=ParentViewControl, Path=ViewState, Mode=TwoWay }" />
</DataTemplate>
在父视图和每个子视图上,我创建了一个名为ViewState(枚举)的依赖属性。它们通过DataTemplates相互绑定。在每个View的代码隐藏中,我根据用户输入更新此ViewState属性,并将其传播到Parent View,后者又触发DataTemplateSelector。到现在为止还挺好。导航效果很好。
ViewModel信息
父视图有一个ViewModel,它实现了INotifyPropertyChanged作为其DataContext。我正在尝试使用此单个ViewModel将Properties绑定到Parent View和子视图。问题是上面的DataTemplate片段中的DataContext绑定不起作用。 (自从ViewState绑定以来,这对我来说很奇怪。)经过各种尝试使其工作,子视图上的DataContext为null或ViewState控制变量。
我目前正在使用UnityContainer作为我的依赖注入器。
各种尝试
以下是我尝试过的所有失败的其他事情:
1)将ViewModel注册为UnityContainer中的单例,从而在子视图上使用构造函数注入来设置DataContext。 (不起作用,因为DataTemplate资源必须有一个无参数的构造函数。)
2)将ViewModel注册为UnityContainer中的单例,然后在子视图上使用Property Injection来设置DataContext。 (不起作用。我认为这是因为在Xaml中实例化对象时UnityContainer无法正常工作。)
3)为需要ViewModel的每个子视图创建子ViewModel,以显示父ViewModel上已存在的属性。我之前用过这个来解决UnityContainer的Xaml实例化问题。然后,我将DataTemplate中的DataContext绑定替换为关联的子ViewModel。 (因为某些原因,我的父视图的DataContext被设置为ViewState变量而不是保留我在视图的构造函数中设置的ViewModel。这反过来意味着我的父ViewModel上的子ViewModel属性可以找不到绑定到子视图的DataContext。)UserControls的Content和DataContext是同一个东西吗?设置一个会影响另一个吗?
4)将ViewState依赖项属性从View移动到ViewModel,然后将ContentControl的Content设置为绑定到ViewModel。这违反了MVVM原则,但此时我正在尝试任何方法来实现这一点。 (它不起作用,因为在视图的代码隐藏中更改ViewState时ViewModel不会触发更改。)我没有进一步使用这个,因为我不想更深入地违反MVVM。
结论
在过去的几天里,我在这个网站上发现了大部分这些尝试过的解决方案。我没有接受WPF,Xaml和MVVM的正式培训,因此我怀疑我遗漏了一些明显的东西,或者我正在尝试做一些不可能的事情。我将继续尝试对上述内容进行修改并进行研究,直到找到可行的方法,但我想我会在这里利用集体知识来帮助我找到解决方案。
我更喜欢的是让视图组使用单个ViewModel作为其DataContext,这样我就可以将属性绑定到它们的控件。并且可以通过DataTemplateSelector控制Views的导航。有没有办法做到这一点,我没有看到?
感谢您的时间!
答案 0 :(得分:0)
之前我遇到过类似的问题,我使用RelativeSource绑定运气好。也许尝试这样的事情:
DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContentControl},Path=DataContext}"
只是一个想法。