0

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

windowsgm
  • 1,566
  • 4
  • 23
  • 55
  • One way to circumvent this is to set the scrollbar to always visible. Would that be an option in your case or do you want to hide it when it is not needed? – Manfred Radlwimmer Mar 12 '18 at 11:37
  • @ManfredRadlwimmer Thanks for the response, unfortunately I would need it hidden if not required. – windowsgm Mar 12 '18 at 11:38
  • Could you please post your whole window xaml? I think your window width is less, increase it by 50 or 100 and then it will be fine, because I see that your window border is also cutting off. – Raviraj Palvankar Mar 12 '18 at 11:42
  • 2
    I dont know why but when i change the 'Height' property of your first RowDefinition from auto to a fixed value it workes as expected... Maybe thats an option for you – Tobias Hoefer Mar 12 '18 at 12:55
  • @TobiasHoefer That is odd.... – windowsgm Mar 12 '18 at 12:56

2 Answers2

2

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>
Daniele Sartori
  • 1,674
  • 22
  • 38
  • As I would like to keep the column width to auto, I tried your second solution. This seems to work well, the column width is set to the widest item in the listbox. I noticed it wouldn't scroll, but fixed this using the following; https://stackoverflow.com/a/16235785/1365650. Last issue I have is if I set the VerticalScrollBarVisibility="Auto" then the bar never appears no matter the listbox length. – windowsgm Mar 12 '18 at 12:32
  • VerticalScrollBarVisibility="Auto" where did you set that? – Daniele Sartori Mar 12 '18 at 12:33
  • using `Width="9*"`and `Width="1*"` you will set 90% and 10% not Auto fit like he wants – Celso Lívero Mar 12 '18 at 12:41
  • @CelsoLívero yes i know it. I also specified it in my answer and i gave him also the option to keep the width to auto – Daniele Sartori Mar 12 '18 at 12:42
  • On the ScrollViewer element. – windowsgm Mar 12 '18 at 12:48
  • 1
    As per Tobias's suggestion, when I set the first Row height to a fixed value as opposed to Auto, then the scrollbar visibility works as expected...Can't for the life of me figure out why. – windowsgm Mar 12 '18 at 13:02
  • @windowskm check the edit. If you want to keep the Height of the row set to Auto (to use text wrapping features) – Daniele Sartori Mar 12 '18 at 14:30
  • Unfortunately, when I bind the Height then my work around to get the mouse wheel scrolling working no longer works. :/ – windowsgm Mar 12 '18 at 16:13
  • @windowskm i have no control on what you do in your project. With the code you gave to us, it's working for me. It scrolls with the mousewheel and it doesn't cut the scrollbar. – Daniele Sartori Mar 12 '18 at 16:15
0

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.

Celso Lívero
  • 716
  • 2
  • 14
  • 18
  • Thanks for the resposne. This appears to cause the exact same behaviour, see screenshot; https://ibb.co/dhOWV7 – windowsgm Mar 12 '18 at 12:53