Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF dynamic layout: how to enforce square proportions (width equals height)?

Tags:

wpf

xaml

I'm learning WPF and can't figure out how to enfore my buttons to take a square shape.

Here is my XAML Markup:

<Window x:Class="Example"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="368" Width="333">
  <Window.Resources>
    <Style x:Key="ToggleStyle" BasedOn="{StaticResource {x:Type ToggleButton}}"
                            TargetType="{x:Type RadioButton}">
    </Style>
  </Window.Resources>
  <RadioButton Style="{StaticResource ToggleStyle}">
        Very very long text
  </RadioButton>
</Window>

Specifying explicit values for Width and Height attributes seems like a wrong idea - the button should calculate its dimensions based on its contents automagically, but keep its width and height equal. Is this possible?

like image 400
Gart Avatar asked Jun 05 '10 19:06

Gart


4 Answers

Try this - it seems to work in Kaxaml:

<Button 
    MinWidth="{Binding ActualHeight, RelativeSource={RelativeSource Self}}" 
    MinHeight="{Binding ActualWidth, RelativeSource={RelativeSource Self}}">
  Some content
</Button>

(To test, I put a TextBox inside the button, because that's an easy way to change content size without re-parsing the Xaml.)

Edit: sorry, should probably have specified it as a style to match your example:

<Style TargetType="Button" x:Key="SquareButton">
  <Setter Property="MinWidth" Value="{Binding ActualHeight, RelativeSource={RelativeSource Self}}" />
  <Setter Property="MinHeight" Value="{Binding ActualWidth, RelativeSource={RelativeSource Self}}" />
</Style>
like image 152
Dan Puzey Avatar answered Nov 09 '22 13:11

Dan Puzey


The currently accepted answer cannot grow AND shrink. I think I found a better approach, by defining a custom style with a rectangle (stretched uniformly).

<Style x:Key="SquareButton" TargetType="Button">
    <Setter Property="Foreground" Value="White"/>
    <Setter Property="Background" Value="#3a3a3a" />
    <Setter Property="BorderBrush" Value="#5a5a5a"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">

                <Border HorizontalAlignment="Center">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="auto"/>
                        </Grid.ColumnDefinitions>
                        <Rectangle Stretch="Uniform"
                                         Stroke="{TemplateBinding BorderBrush}"
                                         StrokeThickness="4"
                                         Margin="0" 
                                         Fill="{TemplateBinding Background}" 
                                         Panel.ZIndex="1"
                                         />
                        <ContentPresenter Margin="10" 
                           HorizontalAlignment="Center" 
                           VerticalAlignment="Center" 
                           Panel.ZIndex="2" />
                    </Grid>
                    </Border>

            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="#4a4a4a"/>
        </Trigger>
    </Style.Triggers>
</Style>

Btw, you can also create a perfect round button this way. Just replace Rectangle with Ellipse.

like image 41
yvan vander sanden Avatar answered Nov 09 '22 14:11

yvan vander sanden


I think you want to bind button's width to its height, like this:

<Button Name="myButton"
Width="{Binding ElementName=myButton, Path=Height}"
Height="100">
Button Text
</Button>
like image 4
n535 Avatar answered Nov 09 '22 13:11

n535


@Dan Pruzey's answer was good, but did not shrink the square if the window was downsized. What I found to work best was to set the height to auto and the width to that height:

<Button Height="Auto" Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}"/>

This kept the button a square when sizing my window bigger and smaller. Hope this helps someone.

like image 2
Ethan Shoe Avatar answered Nov 09 '22 14:11

Ethan Shoe