WPF - How to conditionally set SizeToContent?

62 Views Asked by At

enter image description here

I have a resizable custom control window where the image stretches until it hits either the available height or the available width, as pictured above. This is my attempt at setting the window's initial size:

Width = 700;
Height = Math.Min(DesiredSize.Height, System.Windows.SystemParameters.PrimaryScreenHeight * 0.75);

How do I set the starting height of the window to be the 'SizeToContent' height, or 75% of the screen height, whichever is less?

If I set SizeToContent = SizeToContent.Height, the image will stretch to the available width while treating the height as infinite, and this will determine the window height. So if the image is much more wide than tall, I will get the layout on the right above but without extra space above and below the picture (which is good). If the image is much more tall than wide, I will get a window much taller than the screen. Setting the MaxHeight to the screen height works okay, but I'd rather have the initial max to be 75% of the screen height while allowing resizing above 75%.

Both the DesiredSize.Height and the ActualHeight always seem to be zero. I've tried what's suggested here, and I've also tried temporarily setting SizeToContent and using the ActualHeight; here's one attempt combining both (at the end of the FooView() constructor pasted below):

MaxWidth = System.Windows.SystemParameters.PrimaryScreenWidth;
MaxHeight = System.Windows.SystemParameters.PrimaryScreenHeight;
Width = 700;
SizeToContent = SizeToContent.Height;
UpdateLayout();
Measure(new Size(Width, double.PositiveInfinity));
Arrange(new Rect(0, 0, DesiredSize.Width, DesiredSize.Height));
UpdateLayout();
Height = ActualHeight;
SizeToContent = SizeToContent.Manual;

Here's another attempt. It sets the height to less than fits even the text and buttons, but if I remove both SizeToContent lines it does at least work to set a maximum initial size of 75% screen height and a max resizing height of 100%.

MaxWidth = System.Windows.SystemParameters.PrimaryScreenWidth;
MaxHeight = System.Windows.SystemParameters.PrimaryScreenHeight * 0.75;
Width = 700;
SizeToContent = SizeToContent.Height;
Loaded += delegate
{
    SizeToContent = SizeToContent.Manual;
    MaxHeight = System.Windows.SystemParameters.PrimaryScreenHeight;
};

FooView.xaml.cs and FooView.xaml:

namespace Foo.View
{
    public partial class FooView : MetroWindow
    {
        private readonly FooViewModel _viewModel;

        public FooView()
        {
            InitializeComponent();

            // command line args

            _viewModel = new FooViewModel(commandLineArguments, Width, Height);
            DataContext = _viewModel;
            _viewModel.Initialize();

            // style, color

            MaxWidth = System.Windows.SystemParameters.PrimaryScreenWidth;
            MaxHeight = System.Windows.SystemParameters.PrimaryScreenHeight;
            Width = 700;
            Height = Math.Min(DesiredSize.Height, System.Windows.SystemParameters.PrimaryScreenHeight * 0.75);
        }
    }
}
<mah:MetroWindow
        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:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        WindowStartupLocation="Manual"
        Top="100"
        Left="100"
        ResizeMode="CanResize"

        <!-- etc -->
        >

    <!-- styles, brushes... -->

    <Grid Background="{DynamicResource BackgroundBrushDark}">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="23" />
        </Grid.RowDefinitions>


        <Border BorderThickness="0" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="3" x:Name="ContentBorder" Margin="0,0,0,0" Background="{Binding BottomRowBrush}">
            <!-- opacity mask -->

            <Grid Background="{StaticResource Background}">
                <Grid Margin="10">
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>

                    <Image Grid.Row="0" Source="{Binding Image}"/>
                    <TextBlock Grid.Row="1" Margin="0,10,0,10" Background="{StaticResource Container2}">
                        <TextBlock Margin="10" TextWrapping="Wrap" FontSize="{Binding FontSize}" Foreground="{StaticResource PrimaryText}" Background="{StaticResource Container2}" Text="{Binding Text}"/>
                    </TextBlock>
                    <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
                        <Button Visibility="{Binding YesVisibility}" x:Name="YES" Margin="0,0,20,0" Height="40" Width="150" FontSize="22" FontWeight="DemiBold" Content="YES" Foreground="{StaticResource CTAPrimary2}" Click="Button_Click"/>
                        <Button Visibility="{Binding NoVisibility}" x:Name="NO" Margin="0,0,20,0" Height="40" Width="150" FontSize="22" FontWeight="DemiBold" Content="NO" Foreground="{StaticResource CTAPrimary2}" Click="Button_Click"/>
                        <Button Visibility="{Binding ContinueVisibility}" x:Name="CONTINUE" Margin="0,0,20,0" Height="40" Width="150" FontSize="22" FontWeight="DemiBold" Content="CONTINUE" Foreground="{StaticResource CTAPrimary2}" Click="Button_Click"/>
                        <Button Visibility="{Binding ExitVisibility}" x:Name="EXIT" Margin="0,0,0,0" Height="40" Width="150" FontSize="22" FontWeight="DemiBold" Content="EXIT" Foreground="{StaticResource PrimaryText}" Click="Button_Click"/>
                    </StackPanel>
                </Grid>
            </Grid>
        </Border>

    <!-- bottom row -->

    </Grid>
</mah:MetroWindow>

0

There are 0 best solutions below