HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Add controls to a canvas and scale their measures relative to it

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
relativecontrolstheirmeasuresandscalecanvasadd

Problem

I have some code which adds components to a canvas at runtime, WPF application. The user enters some values which translate to the amount of controls to be added and where. There is one canvas which will hold all controls. The controls that get added are rectangles and another canvas.

In my MainWindow class I have the following global fields:

Tile tile = new Tile();
Room room = new Room();
Canvas canvas_room;    
List> values = new List>();
double canvasHeight;
double canvasWidth;


Then, I set my measurements according to the values from some textboxes the user has to fill in.

private void setComponents()
    {
        values.Clear();
        values.Add(new Tuple(textBox_lengthRoom, label_errRoomLength, (textBox_lengthRoom.Text).Replace(',', '.')));
        values.Add(new Tuple(textBox_heightRoom, label_errRoomHeight, (textBox_heightRoom.Text).Replace(',', '.')));
        values.Add(new Tuple(textBox_heightTile, label_errTileLength, (textBox_heightTile.Text).Replace(',', '.')));
        values.Add(new Tuple(textBox_lengthTile, label_errTileHeight, (textBox_lengthTile.Text).Replace(',', '.')));
        values.Add(new Tuple(textBox_joints, label_errJoints, (textBox_joints.Text).Replace(',', '.')));

        if (checkInput())
        {
            room.setWidth(Convert.ToDouble(values[0].Item3) * 100);
            room.setHeigth(Convert.ToDouble(values[1].Item3) * 100);

            tile.setHeigth(Convert.ToDouble(values[2].Item3));
            tile.setWidth(Convert.ToDouble(values[3].Item3));
        }
    }


The checkInput() looks if there are only numeric values in the textboxes. After setting all components, I want rescale them so everything fits nicely in perspective of each other on the canvas. First adding the canvas_room to it, and then adding a rectangle to it for each tile.

```
private void setComponentsRelativeToEachOther()
{
//*0.98 so canvas borders don't overlap
canvasHeight = canvas_main.ActualHeight * 0.98;

Solution

A canvas works on absolute positions so shouldn't be used for any relative layouts

However there are several options available in the WPF framework

the one that I think fits your needs most is transformation

once you have your fixed not relative canvas you can apply a transformation to the entire canvas and scale the entire thing, the easiest way to do this is to use a viewbox as this automatically scales its content to fit its available area while maintaining the aspect ratio

another option is if you were trying to do a simple grid layout (eg battleship style) then you can just use a grid and this will fit the available space though with out regard to the aspect ratio

Here is an Example of these 2 alternative layouts


    
        
            
            
        
        
            
                
                
                
                
                
                
                
                
                
                
            
            
                
                
                
                
                
                
                
                
                
                
            
            
            
            
            
            
        
        
            
                
                
                
                
                
            
        
    

Code Snippets

<Window x:Class="WpDemo.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpDemo"
        mc:Ignorable="d"
        Title="Window1" Height="300" Width="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid Grid.Column="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Rectangle Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="3" Grid.RowSpan="2" Fill="Aqua"/>
            <Rectangle Grid.Column="6" Grid.Row="3" Grid.ColumnSpan="3" Grid.RowSpan="4" Fill="Black"/>
            <Rectangle Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="1" Grid.RowSpan="2" Fill="Green"/>
            <Rectangle Grid.Column="1" Grid.Row="7" Grid.ColumnSpan="1" Grid.RowSpan="1" Fill="Red"/>
            <Rectangle Grid.Column="2" Grid.Row="1" Grid.ColumnSpan="2" Grid.RowSpan="1" Fill="Yellow"/>
        </Grid>
        <Viewbox >
            <Canvas Width="200" Height="200">
                <Rectangle Canvas.Top="10" Canvas.Left="30" Width="60" Height="30" Fill="Aqua" />
                <Rectangle Canvas.Top="60" Canvas.Left="30" Width="60" Height="100" Fill="Black"/>
                <Rectangle Canvas.Top="0" Canvas.Left="10" Width="20" Height="20" Fill="Green"/>
                <Rectangle Canvas.Top="10" Canvas.Left="70" Width="80" Height="20" Fill="Red"/>
                <Rectangle Canvas.Top="80" Canvas.Left="10" Width="30" Height="16" Fill="Yellow"/>
            </Canvas>
        </Viewbox>
    </Grid>
</Window>

Context

StackExchange Code Review Q#159696, answer score: 3

Revisions (0)

No revisions yet.