ContentControl切换DataTemplate时内部元素DataContext为空的问题
问题描述
我需要根据变量值切换ContentControl的DataTemplate,编写了如下XAML代码:
<Window.Resources> <DataTemplate x:Key="ReadOnlyStyle"> <TextBlock x:Name="view1" Text="{Binding ProjectName}" Style="{StaticResource TextBlockStyle}"/> </DataTemplate> <DataTemplate x:Key="EditStyle" > <dxe:ComboBoxEdit x:Name="view2" EditValue="{Binding Path='ProjectID', ValidatesOnDataErrors=True}" ItemsSource="{Binding ProjectsList}" ValueMember="ProjectID" DisplayMember="ProjectName"/> </DataTemplate> </Window.Resources> <ContentControl x:Name="view3"> <ContentControl.Style> <Style TargetType="{x:Type ContentControl}"> <Setter Property="ContentTemplate" Value="{StaticResource EditStyle}"/> <Style.Triggers> <DataTrigger Binding="{Binding EditingMode}" Value="2"> <Setter Property="ContentTemplate" Value="{StaticResource ReadOnlyStyle}"/> </DataTrigger> </Style.Triggers> </Style> </ContentControl.Style> </ContentControl>
当前ContentControl的DataContext正常,但模板内的view1和view2的DataContext为空,请问哪里出错了?该如何修复?
问题原因
ContentControl的Content属性未设置,WPF中DataTemplate是用来渲染Content属性内容的,模板内元素的默认DataContext是Content的值,而非ContentControl自身的DataContext。你只设置了ContentControl的DataContext,但没指定要渲染的Content,所以模板里的绑定找不到数据源。
修复方案
有两种可行的修复方式:
方式一:绑定ContentControl的Content属性(推荐)
直接将ContentControl的Content绑定到自身的DataContext,模板内元素会自动继承这个Content作为DataContext,绑定写法更简洁:
<ContentControl x:Name="view3" Content="{Binding}"> <ContentControl.Style> <Style TargetType="{x:Type ContentControl}"> <Setter Property="ContentTemplate" Value="{StaticResource EditStyle}"/> <Style.Triggers> <DataTrigger Binding="{Binding EditingMode}" Value="2"> <Setter Property="ContentTemplate" Value="{StaticResource ReadOnlyStyle}"/> </DataTrigger> </Style.Triggers> </Style> </ContentControl.Style> </ContentControl>
方式二:在DataTemplate中通过RelativeSource绑定到ContentControl的DataContext
如果不想设置Content属性,可以修改DataTemplate内的绑定路径,通过RelativeSource找到父级ContentControl的DataContext:
<!-- 修改ReadOnlyStyle模板 --> <DataTemplate x:Key="ReadOnlyStyle"> <TextBlock x:Name="view1" Text="{Binding DataContext.ProjectName, RelativeSource={RelativeSource AncestorType=ContentControl}}" Style="{StaticResource TextBlockStyle}"/> </DataTemplate> <!-- 修改EditStyle模板 --> <DataTemplate x:Key="EditStyle" > <dxe:ComboBoxEdit x:Name="view2" EditValue="{Binding DataContext.ProjectID, RelativeSource={RelativeSource AncestorType=ContentControl}, ValidatesOnDataErrors=True}" ItemsSource="{Binding DataContext.ProjectsList, RelativeSource={RelativeSource AncestorType=ContentControl}}" ValueMember="ProjectID" DisplayMember="ProjectName"/> </DataTemplate>
推荐使用第一种方式,更符合WPF的设计逻辑,代码也更简洁易维护。
内容的提问来源于stack exchange,提问作者SullenMan
相关产品推荐
相关产品推荐

