WPF/Prism中如何将父ViewModelP属性绑定到子模板控件?
在WPF Prism MVVM中跨DataContext绑定父控件属性
场景说明
你当前用Prism/MVVM/WPF定义了两个ViewModel:
ViewModel代码
public class ViewModelP : BindableBase { private string _stringP; public string StringP { get => _stringP; set => SetProperty(ref _stringP, value); } private ObservableCollection<ViewModelQ> _myQs; public ObservableCollection<ViewModelQ> MyQs { get => _myQs; set => SetProperty(ref _myQs, value); } } public class ViewModelQ : BindableBase { private string _stringQ; public string StringQ { get => _stringQ; set => SetProperty(ref _stringQ, value); } }
对应的ViewP视图代码:
<UserControl x:Class="NamespacePath.ViewP" xmlns:local="NamespacePath" d:DataContext="{d:DesignInstance Type=local:ViewModelP, IsDesignTimeCreatable=False}"> <!--省略UserControl的大部分模板声明--> <DockPanel> <TextBlock Text="{Binding StringP}"/> <!--该绑定生效--> <TabControl ItemsSource="{Binding MyQs}"> <TabControl.Resources> <DataTemplate DataType="{x:Type local:ViewModelQ}"> <DockPanel> <TextBlock Text="{Binding StringP}"/> <!--该绑定失效--> <TextBlock Text="{Binding StringQ}"/> <!--该绑定生效--> </DockPanel> </DataTemplate> </TabControl.Resources> </TabControl> </DockPanel> </UserControl>
在ViewModelQ不引用ViewModelP的情况下,完全可以在视图层实现绑定父UserControl的DataContext属性,以下是两种常用方案:
方案1:通过RelativeSource定位父级UserControl
直接修改DataTemplate中失效的绑定,用RelativeSource向上查找父级UserControl,再访问其DataContext的属性:
<TextBlock Text="{Binding DataContext.StringP, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
如果父级层级较深,还可以配合AncestorLevel参数指定查找的层级,避免匹配到其他同类型控件:
<TextBlock Text="{Binding DataContext.StringP, RelativeSource={RelativeSource AncestorType={x:Type UserControl}, AncestorLevel=1}}"/>
方案2:给UserControl命名,用ElementName绑定
先给UserControl设置唯一名称:
<UserControl x:Class="NamespacePath.ViewP" xmlns:local="NamespacePath" d:DataContext="{d:DesignInstance Type=local:ViewModelP, IsDesignTimeCreatable=False}" x:Name="RootView">
然后在DataTemplate中通过ElementName引用这个名称,访问其DataContext属性:
<TextBlock Text="{Binding DataContext.StringP, ElementName=RootView}"/>
注意点
- 两种方案都不需要修改ViewModel结构,完全在视图层解决问题
- 使用ElementName时要确保名称在当前XAML作用域内唯一,避免冲突
- 若后续视图结构调整,要注意RelativeSource的AncestorType是否依然匹配
内容的提问来源于stack exchange,提问作者eriyg
相关产品推荐
相关产品推荐

