如何删除ButtonChrome边框(定义边框模板时)?

时间:2010-12-29 11:31:40

标签: wpf xaml button border

我关注了ChrisF here并撰写了simple demo

  

...在Expression Blend中打开你的项目,   选择按钮,然后右键单击   并选择“编辑模板>编辑a   复制..“。这复制了现有的   模板到一个你可以修改。它的   如果在资源中创建它会更容易   字典。

我可以看到按钮的幕后模板如下面的屏幕截图(资源中的 ButtonChrome )。

我想删除 ButtonChrome 的白色渐变边框,并保持按钮UI的其他所有内容保持原样。我怎么能这样做?

PS。为了简化问题,我使用ButtonChrome作为我视图的常规控件。我浏览了属性,但仍然不知道在哪里删除“白色”边框。

ButtonChrome 正在使用中) alt text

(资源中的 ButtonChrome alt text

7 个答案:

答案 0 :(得分:16)

WPF的一个很棒的功能是能够在完全交换控件外观的同时利用控件的行为。您可以完全删除chrome并创建符合您要求的自定义外观。

<强>示例

 <Style x:Key="NoChromeButton" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Padding" Value="1"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid x:Name="Chrome" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="#ADADAD"/>
                            <Setter Property="Opacity" TargetName="Chrome" Value="0.5"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

检查一下 http://www.designerwpf.com/2008/03/27/wpf-designers-guide-to-styles-and-templates/

此链接现在似乎有效: http://www.designersilverlight.com/2008/03/27/wpf-designers-guide-to-styles-and-templates/

答案 1 :(得分:10)

我认为没有一种简单的方法可以摆脱那种白色边界。调用的实际例程是DrawInnerBorder,它在ButtonChrome中从OnRender中调用。

protected override void OnRender(DrawingContext drawingContext)
{
    Rect bounds = new Rect(0.0, 0.0, base.ActualWidth, base.ActualHeight);
    this.DrawBackground(drawingContext, ref bounds);
    this.DrawDropShadows(drawingContext, ref bounds);
    this.DrawBorder(drawingContext, ref bounds);

    // This one draws the white Rectangle
    this.DrawInnerBorder(drawingContext, ref bounds);
}

private void DrawInnerBorder(DrawingContext dc, ref Rect bounds)
{
    if ((base.IsEnabled || this.RoundCorners) && ((bounds.Width >= 4.0) && (bounds.Height >= 4.0)))
    {
        Pen innerBorderPen = this.InnerBorderPen;
        if (innerBorderPen != null)
        {
            dc.DrawRoundedRectangle(null, innerBorderPen, new Rect(bounds.Left + 1.5, bounds.Top + 1.5, bounds.Width - 3.0, bounds.Height - 3.0), 1.75, 1.75);
        }
    }
}

正如我们所看到的,没有属性可以禁用它。 您可以通过在ButtonChrome上设置IsEnabled="False"RoundCorners="False"或将宽度或高度设置为3.99并且“白色边框”消失来验证它。

<强>更新
要禁用ButtonChrome的内边框,您可以创建自己的ButtonChrome来添加此属性。不幸的是,ButtonChrome是密封的,所以我们不能继承它。我试图复制整个类并添加属性DisableInnerBorder,它似乎正在工作。你可以像这样使用它

<local:MyButtonChrome ...
                      DisableInnerBorder="True">

除此之外,它的工作方式与普通的ButtonChrome相同,您还可以添加其他属性等。这个方法可能有一些我没有想到的缺点,但是对于一个小的测试,它工作得很好。

上面有937行代码太多了,无法在SO上发布:)我在这里上传了MyButtonChrome.cs:http://www.mediafire.com/?wnra4qj4qt07wn6

答案 2 :(得分:4)

您不应该尝试自定义ButtonChrome。 * Chrome类是特定于主题的,即它们包含特定Windows主题的实现,您无法覆盖它。查看资源字典中“Microsoft_Windows_Themes”命名空间的声明 - 它可能包含类似PresentationFramework.Aero ...

您应该在自定义模板中执行的操作是使用常用的Border而不是ButtonChrome,并定义在按下或悬停按钮时会更改其背景等的触发器。

以下是一个例子:

<Style x:Key="BaseButtonStyle"
   TargetType="{x:Type ButtonBase}">
<Setter Property="FocusVisualStyle"
        Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="Background"
        Value="{StaticResource ButtonNormalBackground}" />
<Setter Property="BorderBrush"
        Value="{StaticResource ButtonNormalBorder}" />
<Setter Property="BorderThickness"
        Value="1" />
<Setter Property="Foreground"
        Value="{StaticResource ButtonNormalForeground}" />
<Setter Property="HorizontalContentAlignment"
        Value="Center" />
<Setter Property="VerticalContentAlignment"
        Value="Center" />
<Setter Property="Padding"
        Value="5,2,5,2" />
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type ButtonBase}">
            <Border Name="Chrome"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    SnapsToDevicePixels="true"
                    CornerRadius="2">
                <ContentPresenter Margin="{TemplateBinding Padding}"
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                  RecognizesAccessKey="True"
                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
            </Border>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver"
                         Value="True">
                    <Setter Property="Background"
                            Value="{StaticResource ButtonHoverBackground}" />
                    <Setter Property="Foreground"
                            Value="{StaticResource ButtonHoverForeground}" />
                </Trigger>

                <Trigger Property="IsPressed"
                         Value="True">
                    <Setter Property="Background"
                            Value="{StaticResource ButtonPressedBackground}" />
                    <Setter Property="Foreground"
                            Value="{StaticResource ButtonPressedForeground}" />
                </Trigger>
                <Trigger Property="ToggleButton.IsChecked"
                         Value="True">
                    <Setter Property="Background"
                            Value="{StaticResource ButtonHoverBackground}" />
                    <Setter Property="Foreground"
                            Value="{StaticResource ButtonNormalForeground}" />
                </Trigger>
                <Trigger Property="IsEnabled"
                         Value="false">
                    <Setter Property="Foreground"
                            Value="#ADADAD" />
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Setter.Value>
</Setter>

答案 3 :(得分:1)

我意识到这是一个老线程,但是当我尝试做同样的事情并且没有找到任何好的解决方案时,我发现了它。我想我会发布我想出的东西,以防它帮助其他人。

我想要的是扁平按钮,当鼠标悬停时使用普通镀铬。我能找到的最好方法是欺骗并在Grid中使用两行ContentPresenters。一个内容呈现器位于普通的ButtonChrome内,一个位于Border内。一次只显示一个网格行,IsMouseOver触发器中的setter确定显示哪一个。

<Window.Resources>
    <Style x:Key="ButtonFocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>
                    <Rectangle StrokeDashArray="1 2" StrokeThickness="1" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" SnapsToDevicePixels="true" Margin="2"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
        <GradientStop Color="#F3F3F3" Offset="0"/>
        <GradientStop Color="#EBEBEB" Offset="0.5"/>
        <GradientStop Color="#DDDDDD" Offset="0.5"/>
        <GradientStop Color="#CDCDCD" Offset="1"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ButtonNormalBorder" Color="Transparent"/>
    <Style x:Key="ActionButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
        <Setter Property="Background" Value="{x:Null}"/>
        <Setter Property="BorderBrush" Value="{x:Null}"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Padding" Value="1"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition  x:Name="ContentWithChrome" Height="0"></RowDefinition>
                            <RowDefinition  x:Name="ContentWithBorder" Height="Auto"></RowDefinition>
                        </Grid.RowDefinitions>
                        <Themes:ButtonChrome Grid.Row="0" x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RenderDefaulted="{TemplateBinding IsDefaulted}" SnapsToDevicePixels="true">
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Themes:ButtonChrome>
                        <Border Grid.Row="1" Margin="0,2,0,2">
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Height" TargetName="ContentWithChrome" Value="Auto" />
                            <Setter Property="Height" TargetName="ContentWithBorder" Value="0" />
                        </Trigger>
                        <Trigger Property="IsKeyboardFocused" Value="true">
                            <Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/>
                        </Trigger>
                        <Trigger Property="ToggleButton.IsChecked" Value="true">
                            <Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="#ADADAD"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

答案 4 :(得分:0)

如果您想要避开WhiteBorder,则必须更改BorderBrush = Transparent

<Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true" 
                        Background="{TemplateBinding Background}" BorderBrush="Transparent"
                         RenderDefaulted="{TemplateBinding IsDefaulted}" RenderMouseOver="{TemplateBinding IsMouseOver}"
                          RenderPressed="{TemplateBinding IsPressed}">
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True"/>
                        </Microsoft_Windows_Themes:ButtonChrome>

如果你想修改其他一些东西,你必须创建自己的ControlTemplate

请这个链接

http://mark-dot-net.blogspot.com/2007/07/creating-custom-wpf-button-template-in.html

这里他们有不同的按钮模板

答案 5 :(得分:0)

与Me Leak讨论了一段时间后,我终于得到了我的问题的最终解决方案!谢谢Meleak!

您可以下载solution source codes here

答案 6 :(得分:0)

选项还可以使用其他库,如telerik或xceed(也可用于免费商业用途)。在我的解决方案中,我创建了一个类,它是从Xceed.Wpf.Toolkit.Chromes.ButtonChrome派生出来的(Microsoft ButtonChrome是密封的)。 在我的ResourceDictionary中,我实现了一个由Blend for VS创建的Combobox样式。 在ToggleButton的ControlTemplate中,我实现了以下代码:

<ControlTemplate TargetType="{x:Type ToggleButton}">
    <p:ButtonChromeManaged x:Name="Chrome"
                           Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"
                           Background="Transparent"
                           BorderBrush="Transparent"
                           CornerRadius="0"
                           SnapsToDevicePixels="true">
        <p:ButtonChromeManaged.Template>
            <ControlTemplate TargetType="{x:Type p:ButtonChromeManaged}">
                <Border Background="Red">
                    <Path x:Name="Arrow"
                          Margin="0,1,0,0"
                          HorizontalAlignment="Center"
                          VerticalAlignment="Center"
                          Data="{StaticResource DownArrowGeometry}"
                          Fill="Black" />
                </Border>
            </ControlTemplate>
        </p:ButtonChromeManaged.Template>

在这里你只能看到最不礼貌的stuf。您知道要做DownArrowGeometry等等。 我希望这可以帮助别人; - )