Search code examples
c#wpftextboxwindow-resizestretch

How to have a window size that adapts to its content size and vice versa?


This is quite a conundrum to me because I have quite a mess about it. So let's imagine having a window with SizeToContent="WidthAndHeight"

<Window x:Class="Test.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:Test"
    mc:Ignorable="d" Title="MainWindow" SizeToContent="WidthAndHeight" >
    
    <ListBox Name="lbxInfo" Margin="10" FontSize="30" Grid.Row="0"/>
</Window>

so the window has to adapt to its content. Easy peasy.

But here comes the hard part. The content is variable and adapts stretches the window size. So the biggest string well be correctly stretched.

lbxInfo.Items.Add(new TextBox() { Text="AAA", Background = Brushes.Aqua, HorizontalContentAlignment= HorizontalAlignment.Stretch  });
lbxInfo.Items.Add(new TextBox() { Text = "BBB BBB", Background = Brushes.LavenderBlush, HorizontalContentAlignment = HorizontalAlignment.Stretch });
lbxInfo.Items.Add(new TextBox() { Text = "CCC CCC CCC", Background = Brushes.Lime, HorizontalContentAlignment = HorizontalAlignment.Stretch });

Here's the result:

enter image description here

instead I wish it was this one:

enter image description here

so I wish each element to stretch (resize/adjust) to the largest of them.

The only way to achieve I can think this is to have a first loop on the elements calculate the biggest, then set the size of the window upon the result.

Is there any efficient way to do it?

*** ADD ***

Following Clemens solution I have done this in code behind and that works wonder!

var lbxInfo = new ListBox() { FontSize= 30 };
wndMain.Content = lbxInfo ;
lbxInfo.Items.Add(new ListBoxItem() { Content = "AAA", Background = Brushes.Aqua });
lbxInfo.Items.Add(new ListBoxItem() { Content = "BBB BBB", Background = Brushes.LavenderBlush });
lbxInfo.Items.Add(new ListBoxItem() { Content = "CCC CCC CCC", Background = Brushes.Lime });

and the result is magnificient!

enter image description here


Solution

  • Use a ListBox with HorizontalContentAlignment of its ListBoxItems set to Stretch:

    <ListBox ItemsSource="{Binding Items}">
        <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBox Text="{Binding Text}" FontSize="30">
                    <TextBox.Background>
                        <SolidColorBrush Color="{Binding Color}"/>
                    </TextBox.Background>
                </TextBox>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>