首页 > 解决方案 > ContentPresenter 在触发器调用两次以上后失去数据绑定

问题描述

我创建了一个扩展按钮,其中包含由 XAML 中的触发器调用的 2 种不同边框样式。两者共享相同的 contentpesenter,但在更改边框样式两次以上后,contentpresenter 中的内容无法显示。

下面是整个项目的链接,其中包含一个演示问题的测试床应用程序,我认为问题出在下面的 XAML 中,但我看不出它为什么会中断:

示例按钮应用程序

       <Style.Resources>
        <ContentPresenter x:Key="ButtonContent" Margin="5" HorizontalAlignment="Center" 
               Content="{Binding Content}"/>
    </Style.Resources>


    <Setter Property="Template">
         <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid Margin="{Binding KeyMargin}">
                    <Grid Visibility="{Binding RectangleVisibility}">
                        <Grid.OpacityMask>
                            <VisualBrush Visual="{Binding ElementName=rectBorder}" />
                        </Grid.OpacityMask>
                        <Border x:Name="rectBorder" 
                            CornerRadius="{Binding BorderCorners}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            Background="{TemplateBinding Background}"   
                            BorderThickness="{Binding BorderThickness}"/>
                        <Viewbox Stretch="Fill" 
                            StretchDirection="Both">
                            <ContentControl Content="{StaticResource ButtonContent}"/>
                        </Viewbox>
                    </Grid>

                    <Grid Visibility="{Binding EllipseVisibility}">
                        <Ellipse Stroke="{TemplateBinding BorderBrush}"
                            StrokeThickness="{Binding BorderThickness}"
                            Fill="{TemplateBinding Background}">
                        </Ellipse>
                        <Viewbox Stretch="Fill"
                            StretchDirection="Both">
                            <ContentControl Content="{StaticResource ButtonContent}"/>
                        </Viewbox>
                    </Grid>

                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

标签: wpfxaml

解决方案


问题很可能是您不能在可视化树中的多个位置拥有相同的元素(在本例中为 ContentPresenter),并且它最终出现的两个网格之一是未定义的,即 WPF 的实现原型.

要复制元素,这可能有效:

<ContentControl Content="{TemplateBinding Content}"/>

或者在你的情况下

<ContentControl Content="{TemplateBinding Content}" Margin="5" HorizontalAlignment="Center"/>

而不是静态资源。<ContentPresenter/>语法几乎是一个优化的快捷方式(或者您可以在资源上设置 x:Shared="False",但据我所知,将 ContentPresenter 作为静态资源不知道它的用途

如果 Button 内容本身是一个 UIElement,那么它将在可视化树中直接使用,即两次,这也不起作用。更好的解决方案是在控件模板中只包含一次内容并更改其周围的视觉外观,例如,使用触发器来设置 Grid 的 OpacityMask。

另一个说明是,您的控件模板与 Button 的使用位置非常紧密地绑定,直接绑定到当前数据上下文,这降低了它的可重用性。一些简单的修复方法是使用 TemplateBinding 而不是 Binding 分别用于 BorderThickness Margin(而不是 KeyMargin),因为这些是 Button 的现有属性。

为了获得更好的可重用性和更简洁的代码,您应该考虑创建一个从 Button 派生的自定义控件,该控件具有 BorderCorners 的依赖属性、所需的视觉状态(椭圆与矩形)等。您可能还想使用触发器来获得鼠标悬停效果按钮等。玩得开心控制模板!


推荐阅读