contentpresenter.content上的Datatrigger无法正常工作

时间:2012-02-20 10:09:08

标签: wpf datatrigger

我正在尝试基于datatrigger切换contentpresenter的内容。我想在contentpresenter.content中显示usercontrol,如果我有值集,或者我需要显示错误消息。但是绑定在我的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>

2 个答案:

答案 0 :(得分:5)

如果要使用触发器显示UserControl,则应使用ContentControl而不是ContentPresenter。 我更喜欢使用ContentPresenter进行CustomControls,当我在系统中使用UserControl查看自定义数据类型时,以及允许给出动态行为。

示例:要切换ContentPresenter的模板,您需要像这样设置ContentTemplateSelector

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

MyContent,MyContentTemplate&amp; MyContentTemplateSelector是依赖属性,可以在任何使用其实例的地方进行绑定。

阅读

Usage of ContentPresenter

What is the difference between ContentControl and ContentPresenter

问题中提到的绑定不起作用

  

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

绑定是相对于DataContext属性的值解析的。如果在ContentPresenter上声明绑定,则在设置其内容的那一刻,将重新评估绑定。

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

<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>

阅读 How to use triggers for content template,更多详情here

DataTemplate和StaticResource范围的差异是DataTemplate每次应用时都会创建模板的新实例。 然而,StaticResource再次使用相同的UserControl实例(静态实例)。 您还可以使用EventTriggers更改内容基础控制事件,如MouseOver等。

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

...在<x.Resources />标记中:

<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}" />  

答案 1 :(得分:-2)

我通常使用触发器这样......

                        <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检测绑定错误