Wpf contentpresenter.content上的Datatrigger不工作

Wpf contentpresenter.content上的Datatrigger不工作,wpf,datatrigger,Wpf,Datatrigger,我正在尝试根据datatrigger切换contentpresenter的内容。我想在contentpresenter.content中显示usercontrol,如果我有一个值集,或者我需要显示一条错误消息。但是我的datatrigger上的绑定失败,表明找不到属性。我无法为datatrigger检查获取要继承的datacontext。我可以使用注释掉的代码使其工作。但我不明白为什么它不能正常工作 <ContentPresenter.Style> <

我正在尝试根据datatrigger切换contentpresenter的内容。我想在contentpresenter.content中显示usercontrol,如果我有一个值集,或者我需要显示一条错误消息。但是我的datatrigger上的绑定失败,表明找不到属性。我无法为datatrigger检查获取要继承的datacontext。我可以使用注释掉的代码使其工作。但我不明白为什么它不能正常工作

  <ContentPresenter.Style>
            <Style TargetType="{x:Type ContentPresenter}">
                  <Setter Property="Content" Value="{Binding UC}"/>
                <Style.Triggers>
                    <!--<DataTrigger Binding="{Binding DataContext.HasValue,RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}" Value="false">
                        <Setter Property="Content" Value="No preview"/>
                    </DataTrigger>-->
                    <DataTrigger Binding="{Binding HasValue}" Value="false">
                        <Setter Property="Content" Value="No value"/>
                    </DataTrigger> 

                </Style.Triggers> 

            </Style>
        </ContentPresenter.Style>
    </ContentPresenter>

我通常使用这样的触发器

                        <UserControl>
                            <UserControl.Resources>
                                <DataTemplate x:Key="normalTemplate" >
                                     <!-Fav UserControl->
                                </DataTemplate >
                                <DataTemplate x:Key="overWriteTempalte">
                                    <!-Fav UserControl->                                    </DataTemplate>
                            </UserControl.Resources>
                            <ContentPresenter x:Name="ContentField"
                                              Content="{Binding}"
                                              ContentTemplate="{StaticResource ResourceKey=normalTemplate}" />
                            <UserControl.Triggers>
                                <DataTrigger Binding="{Binding Path=MyProperty}" Value="True">
                                    <Setter TargetName="ContentField" Property="ContentTemplate" Value="{StaticResource ResourceKey=overWriteTempalte}" />
                                </DataTrigger>
                            </UserControl.Triggers>
                        </UserControl>


如果绑定存在问题,请使用Snoop检测绑定错误

如果要使用触发器显示UserControl,则应使用ContentControl而不是ContentPresenter。 我更喜欢对CustomControls使用ContentPresenter,当我在系统中对自定义数据类型的视图使用UserControl时,允许提供动态行为

示例:要切换ContentPresenter的模板,需要如下设置ContentTemplateSelector

<ContentPresenter Content="{Binding MyContent}"
                          ContentTemplate="{Binding MyContentTemplate}"
                          ContentTemplateSelector="{Binding MyContentTemplateSelector}"/>

MyContent、MyContentTemplate和MyContentTemplateSelector是依赖属性,可以在使用其实例的任何位置绑定

阅读

问题中提到的装订不起作用

ContentPresenter的DataContext自动设置为的值 它的Content属性,而ContentControl的DataContext不是

绑定是相对于DataContext属性的值进行解析的。如果在ContentPresenter上声明绑定,则在设置其内容时,将重新计算该绑定

ContentControl.Content属性可以根据您的要求在任何触发器上更改。如果要使用它更改ViewModel属性的PropertyChanged事件,则可以通过将DataTrigger与其中包含UserControl实例的DataTemplate绑定,或使用该UserControl的静态资源来使用DataTrigger

<ContentControl>
    <ContentControl.Style>
        <Style TargetType="{x:Type ContentControl}">
            <Setter Value="{StaticResource UnSelectedDataTemplate}" Property="ContentTemplate" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=IsSelected}" Value="True">
                    <Setter Value="{StaticResource SelectedDataTemplate}" Property="ContentTemplate" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ContentContro.Style>
</ContentControl>

阅读,了解更多详细信息

DataTemplate和StaticResource作用域的区别在于DataTemplate每次应用它时都会创建一个新的模板实例。 然而,StaticResource再次使用同一个UserControl实例(静态实例)。 您还可以使用EventTriggers来更改控制事件(如鼠标悬停等)的内容库

替代方法
与上述内容非常相似,但略有不同。在参考资料中定义为数据模板。内容更改的触发基本相同

…在
标记中:

<DataTemplate x:Key="DesignerTemplate" DataType="{x:Type vm:SolutionViewModel}">
    <vw:SolutionDesignerView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SolutionViewModel}">
    <ContentControl Content="{Binding }">
        <ContentControl.Style>
            <Style TargetType="{x:Type ContentControl}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsLoaded}" Value="True">
                        <Setter Property="ContentTemplate" Value="{StaticResource DesignerTemplate}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</DataTemplate>

…然后:

<ContentControl Content="{Binding Solution}" />  


这是错误的。UserControl上的触发器必须是EventTrigger类型。@用户控件的IAbstract绑定不能通过提供类型。。。静态资源需要声明为fr用户控件实例,然后将其绑定为内容才能工作。Joe-由于此用户控件显示为基于viewmodel的content presenter的内容,因此将使用绑定数据触发器。。。。当你想基于UserControl属性显示时使用的事件触发器我已经想出了编码的解决方案。你在这里提供了一些很好的信息。我可以将样本粘贴到您的答案中,您可以编辑和修改。这将奖励你赏金,可能还有一些额外的选票。当然,你可以加上。。我也在添加一些信息。。感谢您的赏金赏金窗口在24小时内不会打开。@IAbstract没问题:)要直接解决OP的问题,
{Binding HasValue}
触发器不起作用,因为
ContentPresenter.DataContext
设置为
ContentPresenter.Content
的值。因此,一旦内容设置为
ViewModel.UC
value,它就会尝试查找
UC.HasValue
,而不是
ViewModel.HasValue
,可以理解失败了。出于同样的原因,相对源方法也起作用。这些信息可以在您提供的第一个链接下找到,但我认为在您的答案中明确指出它会很有用。