如何在WPF中创建圆角按钮?

91

我需要在WPF中创建一个圆角、光泽的按钮,请问需要哪些步骤?


2
圆角的基础是使用Border或Rectangle类,以及Radius属性。 - Kieren Johnstone
1
@KierenJohnstone 当然可以,但是Button类没有这些属性。那么你怎么为Button做呢? - BrainSlugs83
18个回答

218

我知道这篇帖子非常老,但我有一个答案,在上面的答案中令人惊讶地缺失了,并且比大多数答案都要简单得多。

<Button>
    <Button.Resources>
        <Style TargetType="Border">
            <Setter Property="CornerRadius" Value="5"/>
        </Style>
    </Button.Resources>
</Button>

因为按钮控件的默认ControlTemplate使用了一个Border元素,所以向Button的资源添加一个Border样式将该样式应用于该Border。这使您可以添加圆角而无需制作自己的ControlTemplate或编写任何代码。它还适用于所有种类的按钮(例如ToggleButton和RepeatButton)。


1
这个解决方案非常简单而优雅。虽然按钮对象没有边框,但我仍然喜欢它,只是不太理解它的工作原理。 - Rod
6
它能够工作是因为Button确实有一个边框。 Button的ControlTemplate包含一个Border控件,并在其中显示其他所有内容。 - Keith Stein
哦,好的@KeithStein,我对按钮控件有一个误解。谢谢! - Rod
令人惊讶的是,它在Windows Embedded 7上无法工作。我正在尝试查找按钮的默认ControlTemplate。 - Olorunfemi Davis
这个解决方案不错,但Crandel发布的解决方案更好一些。 - Dr. Cogent

74

你需要为按钮创建自己的ControlTemplate。只需查看示例,创建名为RoundCorner的样式,并在其中更改或创建自己新的Control Template,其中包含带有圆角(CornerRadius=8)的边框、一些背景和其他触发器效果。如果您拥有或了解Expression Blend,则可以很容易地完成此操作。

<Style x:Key="RoundCorner" TargetType="{x:Type Button}">
    <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="grid">
                    <Border x:Name="border" CornerRadius="8" BorderBrush="Black" BorderThickness="2">
                        <Border.Background>
                            <RadialGradientBrush GradientOrigin="0.496,1.052">
                                <RadialGradientBrush.RelativeTransform>
                                    <TransformGroup>
                                        <ScaleTransform CenterX="0.5" CenterY="0.5" 
                                                        ScaleX="1.5" ScaleY="1.5"/>
                                        <TranslateTransform X="0.02" Y="0.3"/>
                                    </TransformGroup>
                                </RadialGradientBrush.RelativeTransform>
                                <GradientStop Offset="1" Color="#00000000"/>
                                <GradientStop Offset="0.3" Color="#FFFFFFFF"/>
                            </RadialGradientBrush>
                        </Border.Background>
                        <ContentPresenter HorizontalAlignment="Center"
                                          VerticalAlignment="Center"
                                          TextElement.FontWeight="Bold">
                        </ContentPresenter>
                    </Border>

                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Background" TargetName="border">
                            <Setter.Value>
                                <RadialGradientBrush GradientOrigin="0.496,1.052">
                                    <RadialGradientBrush.RelativeTransform>
                                        <TransformGroup>
                                            <ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1.5" ScaleY="1.5"/>
                                            <TranslateTransform X="0.02" Y="0.3"/>
                                        </TransformGroup>
                                    </RadialGradientBrush.RelativeTransform>
                                    <GradientStop Color="#00000000" Offset="1"/>
                                    <GradientStop Color="#FF303030" Offset="0.3"/>
                                </RadialGradientBrush>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="BorderBrush" TargetName="border" Value="#FF33962B"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Opacity" TargetName="grid" Value="0.25"/>
                    </Trigger>

                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

使用

<Button Style="{DynamicResource RoundCorner}" 
        Height="25" 
        VerticalAlignment="Top" 
        Content="Show" 
        Width="100" 
        Margin="5" />

当鼠标悬停时,我将边框放在具有矩形背景的网格之外。感谢指出边框元素需要在网格内部,并且ContentPresenter也具有对齐设置。 - yancyn
281
天啊,为了得到圆角,所有这些都是必要的吗? - BrainSlugs83
3
同时,它会使我的按钮变得非常暗,并且无法给它们圆角。(使用WPF 4.0) :( - BrainSlugs83
17
这就是使WPF如此令人愉悦的原因。 - lfalin
10
我认为不是所有东西都是必要的。回复者让他很容易地从使用Blend生成的自动生成代码中复制了那个可怕的东西。这就是为什么他得到了所有那些“神圣的粪便”,也是为什么它的格式如此之差。在我看来,应该接受回复,但绝对不能点赞。但是,你可以随意简化这个回复的基本内容(省略颜色、悬停等)并发布它。我一定会给你+1。 - Konrad Viltersten
8
删除WPF表单 => 插入WebView => border-radius: 8px => Presto - ikwillem

58

不改变默认样式的最简单解决方案是:

<Style TargetType="Button" x:Key="RoundButton">
    <Style.Resources>
        <Style TargetType="Border">
            <Setter Property="CornerRadius" Value="5" />
        </Style>
    </Style.Resources>
</Style>

那么只需像这样定义您的按钮:

<Button Style="{DynamicResource RoundButton}" />

Style.Resources 是我错过的部分。我曾尝试在 App.Xaml 中的 Style 中使用 Button.Resources,但无济于事。完美。 - MemeDeveloper

31

这是一个更加简约的控件模板,可以使按钮拥有圆角,但您将不会看到任何悬停或点击的视觉效果。但是根据需要,您可以在控件模板中添加这些效果。我当时使用的是黑色背景,因此背景为白色。

<Style x:Key="RoundedButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border CornerRadius="15" Background="White" BorderThickness="1" Padding="2">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
我使用下面这篇博客中的控件模板作为起点: http://shihac-sharp.blogspot.com.au/2012/05/button-with-rounded-corners-in-wpf.html

11

你可以尝试这个……

 <Border BorderBrush="Black" Name="MyBorder"  
            Height="78" 
            Background="Red" 
            Width="74" 
            CornerRadius="3">
        <Button Width="{Binding MyBorder.Width}" 
                Height="{Binding MyBorder.Height}" 
                Content="Hi" Background="Red"/>
    </Border>

更容易实现。 - Zorkind
4
可以,按钮的背景必须是透明的。 - Emanuele Benedetti
有点奏效。按钮的命中测试会导致其圆度丢失。 - RubberDuck
嗯,我会为此找到解决方案。谢谢提供信息。 - Shakir Ahmed

7
尽管时间已过去多年,但我认为思考不同的方法来解决这个问题是有趣的。
重新创建所有按钮模板的方式是一种很好的方法,如果您想改变一切,但对于初学者或者只是想将按钮的圆角处理掉的人来说,这是令人沮丧的。虽然可以只修改少部分内容,但至少也需要更改事件...
在按钮资源中修改“边框”设计的方式也非常棒,特别是对于初学者。但是,如果你想通过更多的参数提高你的设计,那么更改所有按钮可能会非常乏味。
有一种折衷的解决方案:
将以下代码放入窗口/页面资源:
<Style TargetType="Border" x:Key="RoundMe">
    <Setter Property="CornerRadius" Value="4"/>
</Style>

那么对于按钮:

  <Button.Resources>
        <Style TargetType="Border" BasedOn="{StaticResource RoundMe}"/>
    </Button.Resources>

7
最简单的方法是:
<Button Content="OK"
            Background="#D73C46"
            Foreground="White"
            BorderThickness="0"
            Margin="10,25,10,5"
            Width="275"
            Height="34"
            FontSize="12"
            Click="CloseWindow"
            HorizontalAlignment="Center">
        <Button.Resources>
            <Style TargetType="{x:Type Border}">
                <Setter Property="CornerRadius" Value="3"/>
            </Style>
        </Button.Resources>
    </Button>

4
作为替代方案,你可以编写类似于这样的代码:
    <Border 
            x:Name="borderBtnAdd"
            BorderThickness="1" 
            BorderBrush="DarkGray" 
            CornerRadius="360" 
            Height="30" 
            Margin="0,10,10,0" 
            VerticalAlignment="Top" HorizontalAlignment="Right" Width="30">
        <Image x:Name="btnAdd"
               Source="Recursos/Images/ic_add_circle_outline_black_24dp_2x.png"
               Width="{Binding borderBtnAdd.Width}" Height="{Binding borderBtnAdd.Height}"/>
    </Border>

“按钮”将看起来像这样:

How it could looks like

你可以设置任何其他内容来代替图片。

3
这是@Kishore Kumar答案的简化版本,更贴近默认按钮的样式和颜色。它还修复了他的“IsPressed”触发器顺序错误的问题,因为“MouseOver”将优先执行。
<Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid x:Name="grid">
                        <Border x:Name="border" CornerRadius="2" BorderBrush="#707070" BorderThickness="1" Background="LightGray">
                            <ContentPresenter HorizontalAlignment="Center"
                                      VerticalAlignment="Center"
                                      TextElement.FontWeight="Normal">
                            </ContentPresenter>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" TargetName="border" Value="#BEE6FD"/>
                            <Setter Property="BorderBrush" TargetName="border" Value="#3C7FB1"/>
                        </Trigger>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter Property="BorderBrush" TargetName="border" Value="#2C628B"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="Opacity" TargetName="grid" Value="0.25"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

3

一开始我总是不喜欢看到没有位置说明的代码片段。因此,这里有一个解决方法:

<Window x:Class ...>
    <Window.Resources>
        <Style x:Key="btnRound" TargetType="Button">
            <Style.Resources>
                <Style TargetType="Border">
                    <Setter Property="CornerRadius" Value="5"/>
                </Style>
            </Style.Resources>
        </Style>
    </Window.Resources>
    <Grid>
        <Button Content="Select" Click="Select_Click" Style="{StaticResource btnRound}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Padding="10,2"/>
    </Grid>
</Window>

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

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