RadButton unwanted white border

1 Answer 46 Views
Buttons
Nn
Top achievements
Rank 1
Nn asked on 10 Jan 2023, 09:35 AM

I'm currently reviewing the latest trial WPF <PackageReference Include="Telerik.UI.for.Wpf.70.Xaml.Trial" Version="2022.3.1109" />

I'm trying to create a button with rounded edges and a different colour border. The standard WPF <Button /> works fine but the <telerik:RadButton  /> creates a white inner border and also seems to clip the background on the border edges

See attached example:

The bottom Radbutton has green clipping inside the border edges and an additional white border.

How do make the RadButton appear similar to the standard WPF button (I want it to look like button at top but using RadButton)?

Code:

<Window x:Class="TelerikWpfApp2.MainWindow"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
                Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Button Content="Button" Height="100" Width="100" FontWeight="Bold" FontSize="18"
                Foreground="White"
                Background="Green"
                BorderBrush="Red"
                BorderThickness="5">
            <Button.Resources>
                <Style TargetType="Border">
                    <Setter Property="CornerRadius" Value="5"/>
                </Style>
            </Button.Resources>
        </Button>
        <telerik:RadButton Content="Button" Height="100" Width="100" FontWeight="Bold" FontSize="18" CornerRadius="5"
                           Foreground="White"
                           Background="Green"
                           BorderThickness="5"
                           BorderBrush="#FFFF0505"/>
    </StackPanel>
</Window>

1 Answer, 1 is accepted

Sort by
0
Stenly
Telerik team
answered on 12 Jan 2023, 01:42 PM

Hello,

To achieve this modification, the Loaded event of the RadButton element, as well as the ChildrenOfType extension method could be utilized. The RadButton control has several different visual states that are represented by different Border elements, which are present in its default control template. These borders contain an additional Border element that is responsible for the unwanted white border. This is because both the inner and outer Border elements for each visual state have their BorderThickness property being template-bound to the BorderThickness property of the button. This means that setting the BorderThickness to "5" in the shared code snippet, will apply this thickness to both the inner and outer border of each visual state.

With this in mind, the inner borders of each visual state could be retrieved using the mentioned extension method and their BorderThickness properties could be modified. This way, only the outer borders will have a noticeable border thickness.

The following code snippets show this suggestion's implementation using the code that you have provided:

<telerik:RadButton Content="Button" Height="100" Width="100" FontWeight="Bold" FontSize="18" CornerRadius="5"
                   Foreground="White"
                   Background="Green"
                   BorderThickness="5"
                   BorderBrush="#FFFF0505"
                   Loaded="RadButton_Loaded"/>
private void RadButton_Loaded(object sender, RoutedEventArgs e)
{
    RadButton radButton = (RadButton)sender;

    Border outerBorder = radButton.ChildrenOfType<Border>().FirstOrDefault(x => x.Name == "OuterBorder");
    Border outerMouseOverBorder = radButton.ChildrenOfType<Border>().FirstOrDefault(x => x.Name == "OuterMouseOverBorder");
    Border outerPressedBorder = radButton.ChildrenOfType<Border>().FirstOrDefault(x => x.Name == "OuterPressedBorder");

    if (outerBorder != null && outerMouseOverBorder != null && outerPressedBorder != null)
    {
        Border outerBorderInnerBorder = outerBorder.ChildrenOfType<Border>().FirstOrDefault();
        Border outerMouseOverBorderInnerBorder = outerMouseOverBorder.ChildrenOfType<Border>().FirstOrDefault();
        Border outerPressedBorderInnerBorder = outerPressedBorder.ChildrenOfType<Border>().FirstOrDefault();

        if (outerBorderInnerBorder != null && outerMouseOverBorderInnerBorder != null && outerPressedBorderInnerBorder != null)
        {
            outerBorderInnerBorder.BorderThickness = new Thickness(0);
            outerMouseOverBorderInnerBorder.BorderThickness = new Thickness(0);
            outerPressedBorderInnerBorder.BorderThickness = new Thickness(0);
        }
    }
}

By doing so, the following result will be present:

With this being said, could you give this suggestion a try?

Regards,
Stenly
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Nn
Top achievements
Rank 1
commented on 12 Jan 2023, 04:42 PM

Thank you for the reply. I don't really like the thought of GUI views being separated from the xaml but I've managed to get this working by re-applying the <ControlTemplate /> to the  <telerik:RadButton.Template />

But I must admit I don't understand yet why this works?

1/ Is there a way to simplify this rather than add the entire Setter Property="Template" theme?

2/ Is there a way to make this work without specifying a concrete theme, eg I've just picked a random theme (eg  BorderBrush="{telerik:VisualStudio2013Resource but would prefer if this could allow themes to be changed at runtime rather than having a concrete theme?

 


<Window x:Class="TelerikWpfApp2.MainWindow"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
                Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Button Content="Button" Height="100" Width="100" FontWeight="Bold" FontSize="18"
                Foreground="White"
                Background="Green"
                BorderBrush="Red"
                BorderThickness="5">
            <Button.Resources>
                <Style TargetType="Border">
                    <Setter Property="CornerRadius" Value="5"/>
                </Style>
            </Button.Resources>
        </Button>
        <telerik:RadButton Content="Button" Height="100" Width="100" FontWeight="Bold" FontSize="18" CornerRadius="5"
                           Foreground="White"
                           Background="Green"
                           BorderThickness="5"
                           BorderBrush="Red">
            <telerik:RadButton.Template>
                <ControlTemplate TargetType="telerik:RadButton">
                    <Grid SnapsToDevicePixels="True">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="OuterMouseOverBorder"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OuterPressedBorder" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Visible</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="Content" Storyboard.TargetProperty="(TextBlock.Foreground)">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{telerik:VisualStudio2013Resource ResourceKey=SelectedBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <DoubleAnimation Duration="0" Storyboard.TargetName="FocusVisual" Storyboard.TargetProperty="Opacity" To="0"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisabledVisual" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Visible</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                        <DoubleAnimation Duration="0" Storyboard.TargetName="Content" Storyboard.TargetProperty="Opacity" To="{telerik:VisualStudio2013Resource ResourceKey=DisabledOpacity}"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="BackgroundVisibility">
                                <VisualState x:Name="BackgroundIsHidden">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Collapsed</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                        <DoubleAnimation Duration="0" Storyboard.TargetName="DisabledVisual" Storyboard.TargetProperty="Opacity" To="0"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="BackgroundIsVisible"/>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="FocusStatesGroup">
                                <VisualState x:Name="Unfocused">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisual" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="00:00:00.150">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Collapsed</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Focused">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisual" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="00:00:00.115">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Visible</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Border x:Name="OuterBorder"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                Background="{TemplateBinding Background}"
                                CornerRadius="{TemplateBinding CornerRadius}"/>
                        <Border x:Name="OuterMouseOverBorder"
                                Opacity="0"
                                CornerRadius="{TemplateBinding CornerRadius}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Background="{telerik:VisualStudio2013Resource ResourceKey=MouseOverBrush}"
                                BorderBrush="{telerik:VisualStudio2013Resource ResourceKey=AccentBrush}"/>
                        <Border x:Name="OuterPressedBorder"
                                Visibility="Collapsed"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                CornerRadius="{TemplateBinding CornerRadius}"
                                BorderBrush="{telerik:VisualStudio2013Resource ResourceKey=AccentDarkBrush}"
                                Background="{telerik:VisualStudio2013Resource ResourceKey=AccentDarkBrush}"/>
                        <Border x:Name="DisabledVisual"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                CornerRadius="{TemplateBinding CornerRadius}"
                                Visibility="Collapsed"
                                BorderBrush="{telerik:VisualStudio2013Resource ResourceKey=ComplementaryBrush}"
                                Background="{telerik:VisualStudio2013Resource ResourceKey=AlternativeBrush}"/>
                        <ContentPresenter x:Name="Content"
                                TextBlock.Foreground="{TemplateBinding Foreground}"
                                Margin="{TemplateBinding Padding}"
                                Content="{TemplateBinding Content}"
                                ContentTemplate="{TemplateBinding ContentTemplate}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
                                ContentStringFormat="{TemplateBinding ContentStringFormat}"
                                RecognizesAccessKey="True"/>
                        <Border x:Name="FocusVisual"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                CornerRadius="{TemplateBinding CornerRadius}"
                                Visibility="Collapsed"
                                BorderBrush="{telerik:VisualStudio2013Resource ResourceKey=AccentMainBrush}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter Property="Foreground" Value="{telerik:VisualStudio2013Resource ResourceKey=SelectedBrush}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </telerik:RadButton.Template>
        </telerik:RadButton>

    </StackPanel>
</Window>

Stenly
Telerik team
commented on 17 Jan 2023, 01:38 PM

The reason why this works and results in the desired look is that the default control template for the RadButton for the VisualStudio2013 theme has been set to this RadButton instance via its Template property. By default, if no theme is chosen via the StyleManager when using the Xaml version of the assemblies, the Office_Black theme will be applied. This theme defines a slightly different control template for the RadButton element, which contains an additional Border element inside each different visual state Border. These additional Border elements result in the unwanted additional white border that is present in the image in your initial reply. This means that you could either modify the default control template for the Office_Black theme or use a different one.

Regarding the first requirement, the only options are either to extract the default control template from the resource dictionaries for the chosen theme or to use the ChildrenOfType extension method to retrieve the elements and modify them in code. Our newer themes are designed in such a way that would prevent the need to use these two options, however, when using the older ones (for example, Office_Black) these are the only available approaches that could be used.

For the second requirement, there is no way to make a generic control template that will only update the values of the properties depending on the chosen theme. Each theme provides a different implementation for the control templates of the elements that are made accordingly to the design of the theme. The only options that come to my mind, would be to either create a custom control template or to modify the one provided by the chosen theme, which could be edited to match the desired look. However, by implementing custom control templates for our controls we cannot guarantee that the control will retain its functionality, nor will we fully provide support for it.

I hope the provided information will be of help to you.

Tags
Buttons
Asked by
Nn
Top achievements
Rank 1
Answers by
Stenly
Telerik team
Share this question
or