.net 如何在 WPF 中创建/制作圆角按钮?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6745663/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create/make rounded corner buttons in WPF?
提问by xorpower
I need to create a rounded corner glossy buttonin WPF. Can anyone please explain me what steps are needed?
我需要在 WPF 中创建一个圆角光泽按钮。任何人都可以请解释我需要哪些步骤?
回答by Kishore Kumar
You have to create your own ControlTemplate for the Button. just have a look at the sample
您必须为按钮创建自己的 ControlTemplate。看看样品
created a style called RoundCorner and inside that i changed rather created my own new Control Template with Border (CornerRadius=8) for round corner and some background and other trigger effect. If you have or know Expression Blend it can be done very easily.
创建了一个名为 RoundCorner 的样式,在里面我进行了更改,而是创建了我自己的带有边框的新控件模板(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>
Using
使用
<Button Style="{DynamicResource RoundCorner}"
Height="25"
VerticalAlignment="Top"
Content="Show"
Width="100"
Margin="5" />
回答by Keith Stein
I know this post is super old, but I have an answer that's surprisingly missing from the above and is also much simpler than most.
我知道这篇文章很旧,但我有一个答案,上面的答案出人意料地遗漏了,而且也比大多数人要简单得多。
<Button>
<Button.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="5"/>
</Style>
</Button.Resources>
</Button>
Since the default ControlTemplate for the Button control uses a Border element, adding a style for Border to the Button's resources applies that style to that Border. This lets you add rounded corners without having to make your own ControlTemplate and without any code. It also works on all varieties of Button (e.g. ToggleButton and RepeatButton).
由于 Button 控件的默认 ControlTemplate 使用 Border 元素,因此将 Border 的样式添加到 Button 的资源会将该样式应用于该 Border。这使您无需制作自己的 ControlTemplate 也无需任何代码即可添加圆角。它也适用于所有种类的按钮(例如 ToggleButton 和 RepeatButton)。
回答by Brian Hinchey
This is more of a minimal control template to get a button with rounded corners, however you will not have any hover or click visual effects. But you can add these to the control template as needed. I was working with a dark background, hence the white background.
这更像是一个最小的控件模板,用于获得带圆角的按钮,但是您不会有任何悬停或单击视觉效果。但是您可以根据需要将这些添加到控件模板中。我正在使用深色背景,因此是白色背景。
<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>
I used the control template from the following blog post as my starting point: http://shihac-sharp.blogspot.com.au/2012/05/button-with-rounded-corners-in-wpf.html
我使用以下博客文章中的控件模板作为起点:http: //shihac-sharp.blogspot.com.au/2012/05/button-with-rounded-corners-in-wpf.html
回答by Shakir Ahmed
You can try this...........
你可以试试这个…………
<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>
回答by Giovanny Farto M.
As alternative, you can code something like this:
作为替代方案,您可以编写如下代码:
<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>
The "Button" will look something like this:
“按钮”看起来像这样:
You could set any other content instead of the image.
您可以设置任何其他内容而不是图像。
回答by Jason Masters
This is an adapted version of @Kishore Kumar 's answer that is simpler and more closely matches the default button style and colours. It also fixes the issue that his "IsPressed" trigger is in the wrong order and will never be executed since the "MouseOver" will take precedent:
这是@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>
回答by Vadim Ovchinnikov
You can use attached properties for setting button border radius (also the same will work for textboxes).
您可以使用附加属性来设置按钮边框半径(同样适用于文本框)。
Create class for attached property
为附加属性创建类
public class CornerRadiusSetter
{
public static CornerRadius GetCornerRadius(DependencyObject obj) => (CornerRadius)obj.GetValue(CornerRadiusProperty);
public static void SetCornerRadius(DependencyObject obj, CornerRadius value) => obj.SetValue(CornerRadiusProperty, value);
public static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.RegisterAttached(nameof(Border.CornerRadius), typeof(CornerRadius),
typeof(CornerRadiusSetter), new UIPropertyMetadata(new CornerRadius(), CornerRadiusChangedCallback));
public static void CornerRadiusChangedCallback(object sender, DependencyPropertyChangedEventArgs e)
{
Control control = sender as Control;
if (control == null) return;
control.Loaded -= Control_Loaded;
control.Loaded += Control_Loaded;
}
private static void Control_Loaded(object sender, EventArgs e)
{
Control control = sender as Control;
if (control == null || control.Template == null) return;
control.ApplyTemplate();
Border border = control.Template.FindName("border", control) as Border;
if (border == null) return;
border.CornerRadius = GetCornerRadius(control);
}
}
Then you can use attached property syntax for multiple buttons without style duplicates:
然后,您可以对多个按钮使用附加属性语法,而无需重复样式:
<Button local:CornerRadiusSetter.CornerRadius="10">Click me!</Button>
<Button local:CornerRadiusSetter.CornerRadius="5, 0, 0, 5">Click me!</Button>
<Button local:CornerRadiusSetter.CornerRadius="3, 20, 8, 15">Click me!</Button>
回答by Osama Ibrahim
in your app.xaml add this part of style :
在您的 app.xaml 中添加这部分样式:
<Application.Resources>
<Style TargetType="FrameworkElement" x:Key="VisibleAnimation">
<Setter Property="Visibility" Value="Collapsed"/>
<Setter Property="Opacity" Value="10"/>
<Setter Property="Height" Value="700"></Setter>
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="0.0" To="1.0" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="Button" x:Key="BTNCORNER">
<Setter Property="Background" Value="White" />
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="7,7,7,7" Background="White" BorderBrush="#ccc" BorderThickness="1,1,1,1" >
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
Button
按钮
<Button x:Name="loginButton"
Style="{StaticResource BTNCORNER}"
Margin="50,20,20,20"
Click="loginButton_Click"
FontSize="20" Width="93" Height="42" />
回答by Enrique A. Pinelo Novelo
Well the best way to get round corners fast and with standard animation is to create a copy of the control template with Blend. Once you get a copy set the corner radius on the Grid tag and you should be able to have your control with full animation functionality and applyable to any button control. look this is the code:
好吧,使用标准动画快速获得圆角的最佳方法是使用 Blend 创建控件模板的副本。获得副本后,在 Grid 标签上设置圆角半径,您应该能够使您的控件具有完整的动画功能并可应用于任何按钮控件。看这是代码:
<ControlTemplate x:Key="ButtonControlTemplate" TargetType="Button">
<Grid x:Name="RootGrid" Background="{TemplateBinding Background}"
CornerRadius="8,8,8,8">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<PointerDownThemeAnimation Storyboard.TargetName="RootGrid" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<!--<Border CornerRadius="8,8,8,8"
Background="#002060"
BorderBrush="Red"
BorderThickness="2">-->
<ContentPresenter x:Name="ContentPresenter"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTransitions="{TemplateBinding ContentTransitions}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"/>
<!--</Border>-->
</Grid>
</ControlTemplate>
I also edited the VisualState="PointerOver" specifically at Storyboard.TargetName="BorderBrush", because its ThemeResource get squared corners whenever PointerOver triggers.
我还专门在 Storyboard.TargetName="BorderBrush" 中编辑了 VisualState="PointerOver",因为只要 PointerOver 触发,它的 ThemeResource 就会得到方角。
Then you should be able to apply it to your control style like this:
然后你应该能够像这样将它应用到你的控件样式中:
<Style TargetType="ContentControl" x:Key="ButtonLoginStyle"
BasedOn="{StaticResource CommonLoginStyleMobile}">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Background" Value="#002060"/>
<Setter Property="Template" Value="{StaticResource ButtonControlTemplate}"/>
</Style>
So you can apply your styles to any Button.
因此,您可以将样式应用于任何 Button。
回答by Joe
Although this question is long-since answered, I used an alternative approach that people might find simpler than any of these solutions (even Keith Stein's excellent answer). So I'm posting it in case it might help anyone.
尽管这个问题早已得到解答,但我使用了一种替代方法,人们可能会发现它比任何这些解决方案都简单(甚至是 Keith Stein 的出色回答)。所以我发布它以防它可能对任何人有所帮助。
You can achieve rounded corners on a button without having to write any XAML (other than a Style, once) and without having to replace the template or set/change any other properties. Just use an EventSetter in your style for the button's "Loaded" event and change it in code-behind.
您可以在按钮上实现圆角,而无需编写任何 XAML(样式除外,一次),也无需替换模板或设置/更改任何其他属性。只需在按钮的“加载”事件中使用您样式中的 EventSetter 并在代码隐藏中更改它。
(And if your style lives in a separate Resource Dictionary XAML file, then you can put the event code in a code-behind file for your resource dictionary.)
(如果您的样式存在于单独的资源字典 XAML 文件中,那么您可以将事件代码放在资源字典的代码隐藏文件中。)
I do it like this:
我这样做:
Xaml Style:
Xml 样式:
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<EventSetter Event="Loaded" Handler="ButtonLoaded"/>
</Style>
Code-Behind:
代码隐藏:
public partial class ButtonStyles
{
private void ButtonLoaded(object sender, RoutedEventArgs e)
{
if (!(sender is Button b))
return;
// Find the first top-level border we can.
Border border = default;
for (var i = 0; null == border && i < VisualTreeHelper.GetChildrenCount(b); ++i)
border = VisualTreeHelper.GetChild(b, i) as Border;
// If we found it, set its corner radius how we want.
if (border != null)
border.CornerRadius = new CornerRadius(3);
}
}
If you had to add the code-behind file to an existing resource dictionary xaml file, you can even have the code-behind file automatically appear underneath that XAML file in the Visual Studio Solution if you want. In a .NET Core project, just give it appropriate corresponding name (e.g if the resource Dictionary is "MyDictionary.xaml", name the code-behind file "MyDictionary.xaml.cs"). In a .NET Framework project, you need to edit the .csproj file in XML mode
如果您必须将代码隐藏文件添加到现有资源字典 xaml 文件中,您甚至可以根据需要让代码隐藏文件自动出现在 Visual Studio 解决方案中的 XAML 文件下。在 .NET Core 项目中,只需为其指定适当的对应名称(例如,如果资源字典为“MyDictionary.xaml”,则将代码隐藏文件命名为“MyDictionary.xaml.cs”)。在.NET Framework项目中,需要以XML方式编辑.csproj文件


