1

I know how to set the corner radius of a button in XAML.

However, I need to set the corner radius of buttons that are created programmatically (dynamic buttons), during runtime. Here's a code example:

    Dim pt As Thickness

    Dim mySolidColorBrush As SolidColorBrush = New SolidColorBrush()
    mySolidColorBrush = CType((New BrushConverter().ConvertFrom("#005EB8")), SolidColorBrush)

    pt.Top = 95
    
    If howMany > 0 Then 
        For i = 0 To howMany - 1
            Buttons(i) = New Button With {
                .Tag = i,
                .Margin = New Thickness(5, 5, 5, 0),
                .Width = 120,
                .Height = 60,
                .Foreground = New SolidColorBrush(Colors.White),
                .Background = mySolidColorBrush,
                .VerticalAlignment = VerticalAlignment.Top,
                .HorizontalAlignment = HorizontalAlignment.Left,
                .FontSize = 16,
                .Content = btnName(i)
                }
            AddHandler Buttons(i).Click, AddressOf ButtonClickDyna
            PNL_Main.Children.Add(Buttons(i))
            pt.Top += 45
        Next
    End If

I was not able to find such information on the internet and have been going through the properties of a button one by one, sadly with no success.

Any help will be much appreciated as I am still a newbie.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
Omnisciens
  • 13
  • 2

2 Answers2

0

feel free to fix any syntax errors

Dim border = DirectCast(Buttons(i).Template.FindName("border", Buttons(i)), Border);
border.CornerRadius = 5;
Firo
  • 30,626
  • 4
  • 55
  • 94
  • Are you sure you only change the template for a specific button instead of a template that would potentially be used for a lot of other buttons too? I didn't check, but my first impression would be, this might not be safe. Maybe you can clarify. – grek40 Jul 12 '22 at 11:18
  • 1
    This takes the template of the button and asks it to get the generated element of this specific button with the name "border". The template itself has no border at all. It only has a factory to create the border. – Firo Jul 12 '22 at 11:28
  • I receive the following message → BC30456 'CornerRadius' is not a member of 'Button'. I guess this is coming from C# and was translated but it's not working in VB, or am I doing something wrong? – Omnisciens Jul 12 '22 at 12:55
  • wrong type in the cast. We are getting the border after all – Firo Jul 12 '22 at 13:04
  • might need to call ApplyTemplate() before. – Firo Jul 12 '22 at 13:05
  • First it said that "value of type integer cannot be converted to cornerradius". So I tried to set the CornerRadius value like that: Dim cornerRadiusValue As New CornerRadius cornerRadiusValue.TopLeft = 5 cornerRadiusValue.TopRight = 5 cornerRadiusValue.BottomLeft = 5 cornerRadiusValue.BottomRight = 5 border.CornerRadius = cornerRadiusValue But now I get a System.NullReferenceException – Omnisciens Jul 12 '22 at 13:25
  • then you have a different template. VS has an option to edit template in documentoverview toolwindow – Firo Jul 12 '22 at 15:10
0

Similar to the linked XAML based solution, I suggest you utilize styles when you create your dynamic buttons. Suppose you create some named resource styles in your window

€dit: in my first version I defined a separate named style for the Border, but as @ASh mentioned, the Border style can be nested within the Button style.

<Window.Resources>
    <Style x:Key="MyButtonStyle" TargetType="Button">
        <Style.Resources>
            <Style TargetType="Border">
                <Setter Property="CornerRadius" Value="5"/>
            </Style>
        </Style.Resources>
        <Setter Property="Margin" Value="5 5 5 0"/>
        <Setter Property="Width" Value="120"/>
        <Setter Property="Height" Value="60"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="Background" Value="#005EB8"/>
        <Setter Property="VerticalAlignment" Value="Top"/>
        <Setter Property="HorizontalAlignment" Value="Left"/>
        <Setter Property="FontSize" Value="16"/>
    </Style>
</Window.Resources>

Then you can assign the MyButtonStyle to each created button.

The following code is in C#, but you should be able to create the equivalent VB code

private void Initializer_OnClick(object sender, RoutedEventArgs e)
{
    var buttonStyle = (Style) FindResource("MyButtonStyle");

    for (int i = 1; i <= 2; i++)
    {
        ButtonsContainer.Children.Add(new Button
        {
            Content = $"Button {i}",
            Style = buttonStyle
        });
    }
}

Usage example, where the "Initializer" Button dynamically creates two more buttons:

<Grid>
    <StackPanel Name="ButtonsContainer" Orientation="Horizontal"
                VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
    <Button Content="Initializer"
            Style="{StaticResource MyButtonStyle}"
            VerticalAlignment="Center" HorizontalAlignment="Center"
            Click="Initializer_OnClick"/>
</Grid>
grek40
  • 13,113
  • 1
  • 24
  • 50
  • That's a great solution and worked like a charm! Thank you so much for the effort you put in this answer. I was stuck on this problem for a while and you saved me. I cannot upvote it unfortunately, since I don't have reputation yet, but I will come later to upvote it. Thanks again! – Omnisciens Jul 12 '22 at 15:52
  • 1
    I don't get why you need to create ResourceDictionary in code behind. this solution- https://stackoverflow.com/a/62494682/1506454 - allows to keep all settings in one place – ASh Jul 12 '22 at 16:23
  • @ASh sounds correct, I'll change the answer. However, I can't validate the result right now, so I hope I don't screw it up :) – grek40 Jul 12 '22 at 17:54
  • @Omnisciens I edited my answer with the remark from ASh, it's a bit less complicated than the original approach regarding the border style definition. – grek40 Jul 13 '22 at 06:16
  • Thanks! This is even better and cleaner :) – Omnisciens Jul 22 '22 at 13:07