How to create/make rounded corner buttons in WPF?

2019-01-21 13:02发布

问题:

I need to create a rounded corner glossy button in WPF. Can anyone please explain me what steps are needed?

回答1:

You have to create your own ControlTemplate for the Button. just have a look at the sample

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.

<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" />


回答2:

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



回答3:

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>


回答4:

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"  Width="{Binding borderBtnAdd.Width}" Height="{Binding borderBtnAdd.Height}" Source="Recursos/Images/ic_add_circle_outline_black_24dp_2x.png"/>
    </Border>

The "Button" will look something like this:

You could set any other content instead of the image.



回答5:

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>


回答6:

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);
    }
}


回答7:

in your app.xaml add this part of style :

   <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>


 then go to your button 

                    <Button x:Name="loginButton"  Style="{StaticResource BTNCORNER}"   Margin="50,20,20,20"  Click="loginButton_Click" FontSize="20" Width="93" Height="42"  />


回答8:

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:

<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.

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.



回答9:

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:

<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>


回答10:

<Button x:Name="btnBack" Grid.Row="2" Width="300"
                        Click="btnBack_Click">
                <Button.Template>
                    <ControlTemplate>
                        <Border CornerRadius="10" Background="#463190">
                            <TextBlock Text="Retry" Foreground="White" 
                                       HorizontalAlignment="Center"                                           
                                       Margin="0,5,0,0"
                                       Height="40"
                                       FontSize="20"></TextBlock>
                        </Border>
                    </ControlTemplate>
                </Button.Template>
            </Button>

This is working fine for me.