You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 16:20:14