windowsgm
windowsgm

Reputation: 1616

Auto Width ListBox with a ScrollBar

The code below and screenshots show the issue I'm having below.

I need to have a listbox with Width set to Auto as the content size is variable. However, the number of items going into the listbox will also change, so sometimes a ScrollBar will be needed. The problem is, Auto Width doesn't seem to play well with a Scrollbar as per the images below. I could add a margin but I do not want a gap when no scroll bar is required.

I notice that this is only a problem when the textbox has a long string placed in it, if there is a short/no string entered, then the scrollBar presents correctly.

Is there a way to do this other than detecting if a ScrollBar is needed and dynamically adding a margin? I feel like there should be a way to achieve this in my XAML while still keeping the listbox column to be Width=Auto.

private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
    for (int i = 0; i < 200; i++)
    {
        lbxDocs.Items.Add("TESTSTRING"+i);
    }

    txtImagePath.Text =
        @"uPPvU18ijL9Tz6fqvwLsymkdxuS8h8jS9afzQ8i7LLXvrb2JO2hmPImVF5Dq5PZpdOkw2sTX9j6GeGL7IsaDuaf1ltY0MdzCRHGTZlUVkMa43meW3gavXAWMHyLPiyfGlHxuXcQOoH8ldxkYuxhVRcSJY3ZyCzlCsPjWuINTQyJCAU5hiDqroXWI8"+
        "uPPvU18ijL9Tz6fqvwLsymkdxuS8h8jS9afzQ8i7LLXvrb2JO2hmPImVF5Dq5PZpdOkw2sTX9j6GeGL7IsaDuaf1ltY0MdzCRHGTZlUVkMa43meW3gavXAWMHyLPiyfGlHxuXcQOoH8ldxkYuxhVRcSJY3ZyCzlCsPjWuINTQyJCAU5hiDqroXWI8";
}

<Window x:Class="Grid_ScrollBar.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:Grid_ScrollBar"
        mc:Ignorable="d" Loaded="MainWindow_OnLoaded"
        TextOptions.TextRenderingMode="ClearType" WindowStartupLocation="CenterScreen"
        TextOptions.TextFormattingMode="Display" Height="400" Width="500">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <TextBox Name="txtImagePath"/>

        <ListBox Name="lbxDocs" Grid.Column="1" Grid.Row="1"/>
    </Grid>
</Window>

Scroll Bar is cut off;

enter image description here

Once we hit the longer string item in the ListBox the width increases to show the rest of the scrollbar;

enter image description here

Upvotes: 1

Views: 1770

Answers (2)

Daniele Sartori
Daniele Sartori

Reputation: 1703

The problem is that you are telling to your textbox to take all the available space, i.e. all the space left by your ListBox. Now since the firsts elements of your listbox take "less" space, WPF grant them the minimum space possible, and it doesn't take in count the scrollbar size.

When you have this kind of problem (size of content that can very) my best advice is to not set width to auto. Instead go with proportional sizing (this will avoid also the the effect of physically shift columns to make more room for your listbox items).

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="9*"/>
        <ColumnDefinition Width="1*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <TextBox Name="txtImagePath" Grid.Column="0" Grid.Row="0" TextWrapping="Wrap" Margin="0,0,10,0"/>

    <ListBox Name="lbxDocs" Grid.Column="1" Grid.Row="1" />
</Grid>

you can add also TextWrapping="Wrap" to show the full text.

However if you really want to keep the width to auto you can force wpf to take in count the scrollbar using

    <ScrollViewer  Grid.Column="1" Grid.Row="1">
        <ListBox Name="lbxDocs"/>
    </ScrollViewer>

EDIT: to fix the problem with the scrollviewer you need to set the height of the listbox to the heigh of the scrollviewer, or the Auto setting will not work:

    <ScrollViewer x:Name="test" Grid.Column="1" Grid.Row="1" VerticalScrollBarVisibility="Auto">
        <ListBox Name="lbxDocs" Height="{Binding ElementName=test, Path=ActualHeight}"/>
    </ScrollViewer>

Upvotes: 2

Celso L&#237;vero
Celso L&#237;vero

Reputation: 726

try adding the scrollview to your listview without changing the rest of xaml

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <TextBox Name="txtImagePath"/>
        <ListBox Name="lbxDocs" 
                 Grid.Column="1" 
                 Grid.Row="1"  
                 ScrollViewer.CanContentScroll="True"
                 ScrollViewer.VerticalScrollBarVisibility="Auto"
                 ScrollViewer.HorizontalScrollBarVisibility="Auto"
        />

Width = "*" means you will use all the rest of the available space. Width = "Auto" means you will adjust the size of your content so that everything fits and not over any excess space

so (as you did) in your window will be column 1 adjusted to the size of the listview and column 0 with the rest of the window.

Upvotes: 0

Related Questions