Search code examples
wpftextboxrounding

Weird WPF Round TextBox


I am new to WPF and I am trying to do a rounded corner textbox. There are a lot of examples I gather from here. However I cannot seems to make it work. Below are the two ways I tried and the results I obtained.

First Way:

<SolidColorBrush x:Key="SubTransparentTextBoxBG" Color="#ffffff" Opacity="0.12"/>        
    <Style TargetType="TextBox">
        <Style.Setters>
            <Setter Property="Background" Value="{StaticResource SubTransparentTextBoxBG}" />
            <Setter Property="FontSize" Value="24px" />
            <Setter Property="FontFamily" Value="Segoe UI Semibold"/>
            <Setter Property="Foreground" Value="White" />
            <Setter Property="Padding" Value="10" />
            <Setter Property="BorderBrush" Value="Red" />
            <Setter Property="BorderThickness" Value="2"/>
        </Style.Setters>
        <Style.Resources>
            <Style TargetType="Border">
                <Setter Property="CornerRadius" Value="10"/>
            </Style>                
        </Style.Resources>            
    </Style>

Result:

enter image description here

Apparently all my Setters took effect but not the Corner Radius

Second Way:

<SolidColorBrush x:Key="SubTransparentTextBoxBG" Color="#ffffff" Opacity="0.12"/>        
    <Style TargetType="TextBox">
        <Style.Setters>
            <Setter Property="Background" Value="{StaticResource SubTransparentTextBoxBG}" />
            <Setter Property="FontSize" Value="24px" />
            <Setter Property="FontFamily" Value="Segoe UI Semibold"/>
            <Setter Property="Foreground" Value="White" />
            <Setter Property="Padding" Value="10" />
            <Setter Property="BorderBrush" Value="Red" />
            <Setter Property="BorderThickness" Value="2"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TextBox">
                        <Border x:Name="border" CornerRadius="10" BorderBrush="#000" BorderThickness="2" Background="#fff"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>

        </Style.Setters>

    </Style>

Result:

enter image description here

This time, only the Round Border takes place and the rest of the Setters' property are overwritten.

Can Someone Please Help to point out what are the mistakes in these two ways?


Solution

  • The best way to give the TextBox rounded corners is to overwrite the template.

    The following is your Style, but fixed. It now contains the mandatory parts with their mandatory naming: a content host named PART_ContentHost. In order to make the style setters work, you need to bind the template's controls (in this case the Border properties) to the appropriate properties of the templated parent (the TextBox) using TemplateBinding.

    <Style TargetType="TextBox">
      <Style.Setters>
        <Setter Property="Background"
                Value="{StaticResource SubTransparentTextBoxBG}" />
        <Setter Property="FontSize"
                Value="24px" />
        <Setter Property="FontFamily"
                Value="Segoe UI Semibold" />
        <Setter Property="Foreground"
                Value="White" />
        <Setter Property="Padding"
                Value="10" />
        <Setter Property="BorderBrush"
                Value="Red" />
        <Setter Property="BorderThickness"
                Value="2" />
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="TextBox">
              <Border CornerRadius="10"
                      Margin="{TemplateBinding Margin}"
                      Background="{TemplateBinding Background}"
                      BorderBrush="{TemplateBinding BorderBrush}"
                      BorderThickness="{TemplateBinding BorderThickness}"
                      Padding="{TemplateBinding Padding}">
    
                <!-- The required part with the required name -->
                <ScrollViewer x:Name="PART_ContentHost"/>
              </Border>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style.Setters>
    </Style>
    

    Wrapping the TextBox in a Border with rounded corners will still leave the TexBox with sharp corners that will overlap the rounded corners of the surrounding Border.

    Some controls have mandatory template elements (parts) which must be part of the ContorlTemplate and have a special name. When those parts are missing or the name doesn't match the required name, then the functionality of the templated control might get broken. To know the parts and their names of TextBox visit TextBox Parts. To know the named parts of all WPF controls visit Control Styles and Templates. This links also contains an example of the actual Style and Template.

    An alternative approach to get the required template parts is to select the control you wish to template and then open the XAML designer view. Right click on the selected control and select Edit Template. In the popup select Edit a Copy. A dialog opens. Here you can give the extracted template a name and set the location where the extracted template will be moved to. Now you can edit this template which already has all the required parts.