自定义控件内容被使用两次?

问题描述

我有一个自定义控件,我在其中扩展了ToggleButton支持用户单击时更改颜色。它利用为ControlTemplate设置Border如下:

<ToggleButton
    x:Class="KwTools.Wpf.Controls.ToggleButtonControls.ColorChangingToggleButton"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    d:DesignHeight="450"
    d:DesignWidth="800"
    mc:Ignorable="d">
    <ToggleButton.Style>
        <Style targettype="{x:Type ToggleButton}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate targettype="ToggleButton">
                        <Border x:Name="border" Background="{TemplateBinding Background}" Focusable="False">
                            <ContentPresenter x:Name="toggleButtonContentPresenter" TextElement.Foreground="{TemplateBinding Foreground}" />
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsChecked" Value="True">
                                <Setter TargetName="toggleButtonContentPresenter" Property="TextElement.Foreground" Value="{Binding CheckedForeground,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ToggleButton}}}" />
                                <Setter TargetName="border" Property="Background" Value="{Binding CheckedBackground,AncestorType={x:Type ToggleButton}}}" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ToggleButton.Style>
</ToggleButton>

问题是,如果我要使用此控件并修改Border,请说如下:

<cctb:ColorChangingToggleButton x:Name="foo" cctb:ColorChangingToggleButton.ToggledBackground="Orange" 
                                cctb:ColorChangingToggleButton.ToggledForeground="Yellow"
                                Content="Test it"
                                Background="Yellow" Foreground="Red"
                                HorizontalAlignment="Center" HorizontalContentAlignment="Center"
                                VerticalAlignment="Center" VerticalContentAlignment="Center">
   <Border CornerRadius="3"/>
</cctb:ColorChangingToggleButton>

然后我得到这个错误

内容属性设置了多次。

如何获得此信息以便可以在此处编辑自定义控件的边框?

解决方法

然后我收到错误消息“属性'content'设置了多次。

您完全按照错误状态进行操作,将内容设置两次。

  1. 您可以通过Content属性在此处设置内容:Content="Test it"
  2. 您直接在标签内设置内容:<Border CornerRadius="3"/>

删除这两个中的一个,以便仅将内容设置一次。

如何获得此信息以便可以在此处编辑自定义控件的边框?

添加边框作为内容时,它不会修改或替换控件模板中的边框,而是将其添加为子控件,但这不是您想要的。

如果您想自定义控件的边框,请向TemplatedBinding的{​​{1}}属性添加CornerRadius,因为Border没有此属性。

ToggleButton

然后根据您的默认样式创建样式并自定义<ControlTemplate TargetType="ToggleButton"> <Border x:Name="border" Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding Border.CornerRadius}" Focusable="False"> <ContentPresenter x:Name="toggleButtonContentPresenter" TextElement.Foreground="{TemplateBinding Foreground}" /> </Border> <!-- ...other code. --> </ControlTemplate>

CornerRadius

最后,使用<Style x:Key="MyColorChangingToggleButtonStyle" TargetType="{x:Type cctb:ColorChangingToggleButton}" BasedOn="{StaticResource {x:Type cctb:ColorChangingToggleButton}}"> <Setter Property="Border.CornerRadius" Value="3"/> </Style> 将其应用于切换按钮。

StaticResource

更新您的评论。因为找不到控件的样式是在控件的XAML中定义的,所以会出现资源未找到错误。

要解决此问题,您必须提取样式并将其定义在资源字典中,该资源字典可从您定义派生样式的位置进行访问,例如<cctb:ColorChangingToggleButton x:Name="foo" Style="{StaticResource MyColorChangingToggleButtonStyle}" Content="Test it" ...> 中的应用程序资源。然后,您也可以删除App.xaml XAML,不再需要它。

ToggleButton

通常(但不是强制性的),您将创建一个单独的自定义控件项目,并在其中定义该类,然后创建上述样式(通过名称显式引用和隐式引用),以便将其应用于所有控件实例这种类型的。您可以将此样式放入主题资源词典之一,例如<!-- Explicit style for referencing via static/dynamic resource --> <Style x:Key="ColorChangingToggleButtonStyle" TargetType="{x:Type cctb:ColorChangingToggleButton}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type cctb:ColorChangingToggleButton}"> <Border x:Name="border" Background="{TemplateBinding Background}" Focusable="False"> <ContentPresenter x:Name="toggleButtonContentPresenter" TextElement.Foreground="{TemplateBinding Foreground}" /> </Border> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="True"> <Setter TargetName="toggleButtonContentPresenter" Property="TextElement.Foreground" Value="{Binding CheckedForeground,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ToggleButton}}}" /> <Setter TargetName="border" Property="Background" Value="{Binding CheckedBackground,AncestorType={x:Type ToggleButton}}}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- Implicit style,automatically applied to all of your custom controls in scope --> <Style TargetType="{x:Type cctb:ColorChangingToggleButton}" BasedOn="{StaticResource ColorChangingToggleButtonStyle}"/> ,请参阅这些参考资料以获取更多信息。