我正在尝试基于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>
答案 0 :(得分:5)
如果要使用触发器显示UserControl,则应使用ContentControl而不是ContentPresenter。 我更喜欢使用ContentPresenter进行CustomControls,当我在系统中使用UserControl查看自定义数据类型时,以及允许给出动态行为。
示例:要切换ContentPresenter的模板,您需要像这样设置ContentTemplateSelector
<ContentPresenter Content="{Binding MyContent}"
ContentTemplate="{Binding MyContentTemplate}"
ContentTemplateSelector="{Binding MyContentTemplateSelector}"/>
MyContent,MyContentTemplate&amp; MyContentTemplateSelector是依赖属性,可以在任何使用其实例的地方进行绑定。
阅读:
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检测绑定错误