我有一个子用户控件(Page1),当它在XAML中声明内联时,无法继承我的WPF窗口的DataContext上设置的ViewModel(WizardPageViewModel):
<Window x:Class="WPFToolkitWizard.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="clr-namespace:WPFToolkitWizard"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<common:WizardPageViewModel/>
</Window.DataContext>
<Grid>
<common:MyWizardControl>
<common:MyWizardControl.Pages>
<common:Page1 Title="Page 1" Description="First page" IsValid="true" />
</common:MyWizardControl.Pages>
</common:MyWizardControl>
</Grid>
但是,如果我将其更改为静态资源并按如下方式引用它:
<Window.Resources>
<common:WizardPageViewModel x:Key="vm" />
</Window.Resources>
<common:Page1 Title="Page 1" Description="First page" IsValid="true" DataContext="{StaticResource vm}" />
在Page1中声明的绑定取决于注入的VM工作正常。问题是我想从Window的DataContext属性引用ViewModel,因为这是我们在整个团队中声明我们的VM的方式:
<Window.DataContext>
<common:WizardPageViewModel/>
</Window.DataContext>
我已尝试按如下方式设置绑定,但没有这样的运气:
<common:Page1 Title="Page 1" Description="First page" IsValid="true" DataContext="{Binding}" />
此外,我已经阅读了有关DataContext自动继承的帖子,但它在这种情况下不起作用。
查看详细的调试输出,如下所示:
System.Windows.Data Warning: 60 : BindingExpression (hash=26218178): Default mode resolved to TwoWay
System.Windows.Data Warning: 61 : BindingExpression (hash=26218178): Default update trigger resolved to LostFocus
System.Windows.Data Warning: 62 : BindingExpression (hash=26218178): Attach to System.Windows.Controls.TextBox.Text (hash=35377412)
System.Windows.Data Warning: 67 : BindingExpression (hash=26218178): Resolving source
System.Windows.Data Warning: 70 : BindingExpression (hash=26218178): Found data context element: TextBox (hash=35377412) (OK)
System.Windows.Data Warning: 71 : BindingExpression (hash=26218178): DataContext is null
System.Windows.Data Warning: 65 : BindingExpression (hash=26218178): Resolve source deferred
它声明DataContext为null,但我不知道为什么它不会自动找到我的VM实例。
MyWizardControl是一个用户控件
Page1是ContentControl
答案 0 :(得分:-1)
似乎按照我的预期工作。
从代码的结构我假设common:MyWizardControl
是ItemsControl
,因为它包含Pages
属性。
如果这是真的,那么ItemsControl
元素(在您的情况下是您的网页)会从ItemControl
的源ItemsSource
属性继承ViewModel在你的情况下是ObservableCollection<WizardPageViewModel>
。
由于您未在ItemSource
上设置ItemsControl
属性,因此它是空的,WPF无法为其分配任何数据上下文。
静态版本有效,因为您明确设置它,覆盖DataContext
设置的任何可能的ItemSource
。
话虽如此,你有三个选择:
View
MyWizardViewModel
的{{1}},并将其绑定到ObservableCollection<WizardPageViewModel> Pages {get;set;}
的{{1}}。第一个选项感觉有点脏,但对于演示或教学项目可能没问题。
第二个适用于可重用的Views / ViewModel,如果是Prims,ViewModelLocator将为您在XAML中插入的每个ItemsSource
视图创建一个ViewModel的新实例。如果使用依赖注入框架(如Unity,MEF,Autofac等),则可以在多个WizardPageViewModel
控件中使用ViewModel的单个实例。
第三个选项是首选,因为ViewModel旨在与视图一起使用,Page1
是Page1
,而不是View
(实际上Page1
是它拥有子视图的视图,每个视图都意味着拥有它自己的ViewModel来表示View需要的数据。
第三个选项是最容易实现的,无需使用MVVM框架或依赖注入
编辑:示例
MyWizardControl
XAML:
MyWizardControl
然后您只需为每个ViewModel创建DataTemplates,然后ContenControl将根据DataContext的类型显示正确的模板。见here