当ContentControl的内容为空时,如何显示默认的DataTemplate?

49

我认为这是可能的,但显而易见的方法却不能运行。

目前,我正在这样做:

<ContentControl
    Content="{Binding HurfView.EditedPart}">
    <ContentControl.Resources>
        <Style
            TargetType="ContentControl"
            x:Key="emptytemplate">
            <Style.Triggers>
                <DataTrigger
                    Binding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Content}"
                    Value="{x:Null}">
                    <Setter
                        Property="ContentControl.Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Grid
                                    HorizontalAlignment="Stretch"
                                    VerticalAlignment="Stretch">
                                    <TextBlock>EMPTY!</TextBlock>
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ContentControl.Resources>
</ContentControl>
我没有得到任何绑定错误并且这个程序可以编译。然而,它没有产生预期的结果。我也尝试了显而易见的方法:
<DataTemplate DataType="{x:Null}"><TextBlock>Hurf</TextBlock></DataTemplate>

这段代码无法编译。而且尝试两次设置内容也会失败:

<ContentControl
    Content="{Binding HurfView.EditedPart}">
        <TextBlock>DEFAULT DISPLAY</TextBlock>
</ContentControl>

我能否在不编写自定义模板选择器的情况下完成这个操作?

3个回答

60

很简单,你需要在样式中绑定内容属性。如果控件上存在绑定,则即使该值为 Null,样式也不会覆盖该值。试试这个。

<ContentControl>
    <ContentControl.Style>
        <Style TargetType="ContentControl">
            <Setter Property="Content" Value="{Binding HurfView.EditedPart}" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Content}" Value="{x:Null}">
                    <Setter Property="ContentControl.Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                                    <TextBlock>EMPTY!</TextBlock>
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ContentControl.Style>
</ContentControl>

没问题,这是很常见的错误,人们在尝试使用样式和触发器做更复杂的事情时经常犯。 - Bryan Anderson
2
每次我回来这里,我都会留下评论。谢谢。 - user1228
你好。对于一个失败的转换器,最好的解决方案是从转换过程中返回null并以此进行捕获。不幸的是,无法使用验证来实现这一点... - user1228
这对我来说行不通,我正在使用从这里获取的TransitionControl,它会崩溃,因为Template.FindName("PART_ContentHost", this);返回null... - RvdK
请为网格(或其他顶级面板)命名 PART_ContentHost。 - Bryan Anderson
显示剩余3条评论

26

我今天遇到了同样的问题,偶然看到了这个问题,所以想提供另一种解决方法。由于我不想添加另一个样式触发器,所以我使用了TargetNullValue属性来解决问题,它似乎比被接受的解决方案更易读(尽管被接受的解决方案也有效):

    <ContentControl>
      <ContentControl.Content>
        <Binding Path="ContentViewModel">
          <Binding.TargetNullValue>
            <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
              <TextBlock>EMPTY!</TextBlock>
            </Grid>
          </Binding.TargetNullValue>
        </Binding>
      </ContentControl.Content>
    </ContentControl>

这是一个优雅的解决方案,使用了TargetNullValue。不错的发现。 - juFo
可以工作,但在某些情况下(比如我的情况)会产生绑定错误。虽然我认为这个更易读,但在使用时请检查是否有新的绑定错误。 - Dima
还可以在这里看看:[https://dev59.com/E33aa4cB1Zd3GeqPdXRy],了解`FallbackValue`属性,以防`TargetNullValue`单独使用无法解决问题。 - Angle.Bracket

2

在ContentControl的绑定中,您可以将DBNull.Value作为FallbackValue返回,并为DBNull创建一个DataTemplate:

<DataTemplate DataType="{x:Type system:DBNull}">
    <!-- The default template -->
</DataTemplate>

...

<ContentControl Content="{Binding HurfView.EditedPart, FallbackValue={x:Static system:DBNull.Value}}" />

4
有点奇怪...我的理解是首选方法是返回DependencyProperty.UnsetValue。我在一些类型转换器中使用过它,并且效果很好... - user1228
2
@Will,是的,那样可能更好。我写下这个答案已经超过一年了,当时我对WPF的理解还非常不完整... - Thomas Levesque
@Will,你能否添加一个使用DependencyProperty.UnsetValue的答案? - Simon_Weaver
2
@Simon_Weaver 嗯,不是吧?因为我不知道你为什么需要一个?被选中的答案不正确吗? - user1228
我使用了 TargetNullValue={x:Static system:DBNull.Value}<DataTemplate DataType="{x:Type system:DBNull}">,效果非常好。 - marbel82

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接