0
votes

Using WPF, I have a Window, that is filled with one Grid. Currently this Grid has one Row and three Columns, each cell filled with the same UserControl. Future versions might add more Rows to the Grid.

I want to make my window have the size of the Grid.

<Window
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns: ...
    ...
    mc:Ignorable="d"
    d:DesignHeight="600" d:DesignWidth="600"
    Title="MainWindow" Height="600" Width="600">

<Grid Name="MainGrid">
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>
    
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <View:ImageView Grid.Row="0" Grid.Column="0" DataContext="..."/>
    <View:ImageView Grid.Row="0" Grid.Column="1" DataContext="..."/>
    <View:ImageView Grid.Row="0" Grid.Column="2" DataContext="..."/>
</Grid>

The Window has a Width of 600. The Grid will stretch to this window. It will have a Width about 600. The Grid will have three columns with the same Width, something near 200. The ImageView in each cell will stretch to fill the Cell. Each Cell will have a Width about 200.

This determines the Height of the Cells, and thus the Height of the Grid.

Addition: after comments I don't want to resize the window. After it decided about what it should displays and what sizes the controls should have to display it nicely, there is no need to resize it.

For debugging, to see what happens, I resized the mainwindow, and recorded what happens to the various Height / Width / ActualHeight / ActualWidth values.

I noticed that the Grid is resized, such that its Width exactly fills the Width of the Window. Resizing will also Resize the cells and the ImageViews that are in the Cells.

This fitting is not the case with the Height. I can make the Height window Higher and Lower than the Height of the Grid.

I want to set the Height of the window such that it is exactly around the Grid.

I expected something like:

<Window ... Width = "600" Height = "auto" />

Nope, the height is way large than it should be, somewhere near 1000. The Grid is still about 300 x 600.

<Window ... Width = "600" Height = "*" /> 

This leads to an exception.

Maybe Binding? Something like this?

<Window ... Width = "600" Height = "{Binding Height, ElementName=MainGrid, Mode=OneWay}"/>
<Window ... Width = "600" Height = "{Binding ActualHeight, ElementName=MainGrid, Mode=OneWay}"/>

Nope, still way to large.

So, how to make sure that the window is exactly around the Grid?

2
I had to read your question now multiple times and im still not sure, what you are asking. Do you want to prevent resizing? Wanna have Scrollbars (or not)? Wanna use the MinHeight of a Control?lokusking
Nope, the height is way large than it should be, somewhere near 1000. The Grid is still about 300 x 600. How do you measure these values? WPF uses device independent pixels, also display scaling should be taken into accountPavel Anikhouski
Lokusking: I noticed, if I resized my main window, the Grid also resizes. The width is filling the complete window. There is some white space below the Grid.Harald Coppoolse
Pavel: I measure them by adding a binding object that puts the Height / Width of the Grid and the main window to my ViewModelHarald Coppoolse

2 Answers

0
votes

Remove the Height from the window and set SizeToContent to Height. However, this will only set the width and height that you expect initially, not on resizing.

<Window
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns: ...
    ...
    mc:Ignorable="d"
    d:DesignHeight="600"
    d:DesignWidth="600"
    Title="MainWindow"
    Width="600"
    SizeToContent="Height">

If you want to resize the window like you describe, it would mean to keep the aspect ratio and this not easy to solve without unexpected effects or you would have to restrict resizing to the horizontal direction only, which is not trivial either. You can have a look at these related questions.

Of course you could also listen for resize events of the window and do custom processing there, but this approach and also the ones above might harm your user experience and could introduce unwanted effects, so maybe it is more advisable to revisit the layout concept.

0
votes

As @thatguy says, what you're asking for is difficult to do well. In general you don't want code that attempts to resize a window after a user resizes it because you'll get conflicts between what the user's trying to do and the code wants to do.

That still leaves you with a few options if you don't want your images clipped and want them to fill the window as much as possible, which I think is what you're asking for.

1/ You can maintain the aspect ratios of your images, resize them to fill the screen in one or the other direction, and accept you can get whitespace: enter image description here 2/ You can stretch your images to fill the available space, and hence always fill the entire window as you resize, but losing the aspect ratio: enter image description here Code for these is below. Maintaining aspect ratios:

<Window x:Class="ImageResizeTest.MainWindow"
        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:ImageResizeTest"
        mc:Ignorable="d"
        Title="MainWindow" Width="600" Height="110">
    <Grid Name="MainGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Image Grid.Row="0" Grid.Column="0" Source="https://upload.wikimedia.org/wikipedia/commons/3/30/Googlelogo.png" />
        <Image Grid.Row="0" Grid.Column="1" Source="https://upload.wikimedia.org/wikipedia/commons/3/30/Googlelogo.png" />
        <Image Grid.Row="0" Grid.Column="2" Source="https://upload.wikimedia.org/wikipedia/commons/3/30/Googlelogo.png" />
    </Grid>
</Window>

Stretching images to fill:

<Window x:Class="ImageResizeTest.MainWindow"
        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:ImageResizeTest"
        mc:Ignorable="d"
        Title="MainWindow" Width="600" Height="110">
    <Grid Name="MainGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Image Grid.Row="0" Grid.Column="0" Stretch="Fill" Source="https://upload.wikimedia.org/wikipedia/commons/3/30/Googlelogo.png" />
        <Image Grid.Row="0" Grid.Column="1" Stretch="Fill" Source="https://upload.wikimedia.org/wikipedia/commons/3/30/Googlelogo.png" />
        <Image Grid.Row="0" Grid.Column="2" Stretch="Fill" Source="https://upload.wikimedia.org/wikipedia/commons/3/30/Googlelogo.png" />
    </Grid>
</Window>