Search code examples
c#wpfautosize

Autosize to only some controls


I'm working on a WPF GUI, and I want the window to auto-size to the content, but not to everything: I have some various buttons & other controls, and I want to autosize the width to that. If I add a long item to the list box, I want the window to stay the same size.

Example code:

<Window x:Class="QuickieWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" SizeToContent="WidthAndHeight" ResizeMode="CanMinimize">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal">
            <Button Width="100" Content="Foo" Click="Button_Click"/>
            <Button Width="100" Content="Bar" Click="Button_Click"/>
            <Button Width="100" Content="Baz" Click="Button_Click"/>
        </StackPanel>
        <ListBox Grid.Row="1" Name="TheList" Height="100"/>
    </Grid>
</Window>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        string str = "This is a really long text item that will be wider than the " +
            "three buttons. I want a horizontal scrollbar on the listbox, not a wider " +
            "window. I want the window to size to the buttons, not to this listbox.";
        this.TheList.Items.Add(str);
    }
}

Initially, the window is sized to the buttons:

enter image description here

After adding a long item to the list box, I currently get this:

enter image description here

But I'd rather get this:

enter image description here

(I did that last screenshot by setting MaxWidth on the list box, but that isn't a good solution for the full application: In the full application, it's more than just three buttons; it's buttons, icons, textboxes, labels, etc, and I want the window to autosize to the whole mess, but not to the listbox at the bottom.)


Solution

  • You can bind width of content you do not want to autosize to the actual width of content you do, for example:

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" x:Name="panel">
            <Button Width="100"
                    Content="Foo"
                    Click="Button_Click" />
            <Button Width="100"
                    Content="Bar"
                    Click="Button_Click" />
            <Button Width="100"
                    Content="Baz"
                    Click="Button_Click" />
        </StackPanel>
        <ListBox Grid.Row="1"
                 Name="TheList"
                 Height="100" Width="{Binding ElementName=panel, Path=ActualWidth}" />
    </Grid>
    

    Here I bound width of ListBox to the actual width of panel with buttons, which in this case achieves what you want.