0

I am trying to build a window has three data bound listview controls of indeterminate length. I want all three to be within one scrollview.

In simplest terms the code below is how I would want it to work. Of course the result of the sample xaml code is that the scrollviewer content extends beyond the window and is not scrollable.

I tried using a grid control but this has not worked as hoped. I don't want to have fixed heights and individual scroll bars for each of the listviews as there can be variable amounts of data and it would lead to unnecessary scrolling.

Can anyone provide a way in which to have multiple variable content listviews within one scroll bar?

<Window x:Class="AmultiListTest"
    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:SomeNamespace"
    mc:Ignorable="d"
    Title="AmultiListTest"
    Height="300"
    Width="300">
<StackPanel>
    <ScrollViewer>
        <StackPanel Height="250">
            <Label>List number one</Label>
            <ListView>
                <ListViewItem>list 1 Item 1</ListViewItem>
                <ListViewItem>list 1 Item 2</ListViewItem>
                <ListViewItem>list 1 Item 3</ListViewItem>
                <ListViewItem>list 1 Item 4</ListViewItem>
                <ListViewItem>list 1 Item 5</ListViewItem>
                <ListViewItem>list 1 Item 6</ListViewItem>
                <ListViewItem>list 1 Item 7</ListViewItem>
                <ListViewItem>list 1 Item 8</ListViewItem>
                <ListViewItem>list 1 Item 9</ListViewItem>
            </ListView>
            <Label>List number two</Label>
            <ListView>
                <ListViewItem>list 2 Item 1</ListViewItem>
                <ListViewItem>list 2 Item 2</ListViewItem>
                <ListViewItem>list 2 Item 3</ListViewItem>
                <ListViewItem>list 2 Item 4</ListViewItem>
                <ListViewItem>list 2 Item 5</ListViewItem>
                <ListViewItem>list 2 Item 6</ListViewItem>
            </ListView>
            <Label>List number three</Label>
            <ListView>
                <ListViewItem>list 3 Item 1</ListViewItem>
                <ListViewItem>list 3 Item 2</ListViewItem>
                <ListViewItem>list 3 Item 3</ListViewItem>
                <ListViewItem>list 3 Item 4</ListViewItem>
            </ListView>
        </StackPanel>
    </ScrollViewer>
</StackPanel>

Scott
  • 143
  • 1
  • 9
  • 3
    Just off the top of my head, I'd suggest you try removing the fixed height of 250 from the inner StackPanel, and changing the outer StackPanel to a Grid. The Grid will conform to the size of its parent (the Window in this case). That will force the Grid's content (ScrollViewer) to conform to the size of the Grid, which will trigger the ScrollViewer's scrolling behavior. If that doesn't work, at least you won't have wasted much time trying it. – 15ee8f99-57ff-4f92-890c-b56153 Jun 02 '16 at 13:36
  • And remove the outer StackPanel - you are giving it infininte height. Use a Grid. – paparazzo Jun 02 '16 at 13:48

2 Answers2

2

First of all remove the Height of the stack panel:

<StackPanel Height="250">

to

<StackPanel>

Afterwards bind the height of the scroll

(...)
<ScrollViewer Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Border}},Path=ActualHeight}">
  (...)
</ScrollViewer>

Source: How can I get ScrollViewer to work inside a StackPanel?

Community
  • 1
  • 1
Ricardo Mota
  • 1,194
  • 2
  • 12
  • 25
  • 1
    No need to bind the ScrollViewer's Height. As said in the comments to the question, replace the outer StackPanel by a Grid. As a general rule, never bind Width or Height when you could just use regular layout. – Clemens Jun 02 '16 at 14:13
  • This solution - or switching to a grid for the outer control, both work. However when I try to add a header (that will not scroll) I run into the problem with it being overwritten (if grid) or the relative value of height is now too long. Is there a way I can deduct the height of my header from the relative height binding above? – Scott Jun 02 '16 at 14:35
0

The Scrollviewer height solution posted works. I found a way to include the header by adding a code behind to reduce the scrollviewer height by the height of the header stackpanel. Here is the XAML:

<Window x:Class="AmultiListTest"
    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:SomeNamespace"
    mc:Ignorable="d"
    Title="AmultiListTest"
    Height="300"
    Width="300"
    Loaded="Window_Loaded">
<StackPanel>
    <StackPanel x:Name="SPheader">
        <Label>this is header one</Label>
        <Label>this is header two</Label>
        <Separator />
    </StackPanel >
    <ScrollViewer x:Name="SViewer"
                  Height="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType={x:Type Border}, Mode=FindAncestor}}">
        <StackPanel>
            <Label Content="List number one" />
            <ListView>
                <ListViewItem Content="list 1 Item 1" />
                <ListViewItem Content="list 1 Item 2" />
                <ListViewItem Content="list 1 Item 3" />
                <ListViewItem Content="list 1 Item 4" />
                <ListViewItem Content="list 1 Item 5" />
                <ListViewItem Content="list 1 Item 6" />
                <ListViewItem Content="list 1 Item 7" />
                <ListViewItem Content="list 1 Item 8" />
                <ListViewItem Content="list 1 Item 9" />

            </ListView>
            <Label Content="List number two" />
            <ListView>
                <ListViewItem Content="list 2 Item 1" />
                <ListViewItem Content="list 2 Item 2" />
                <ListViewItem Content="list 2 Item 3" />
                <ListViewItem Content="list 2 Item 4" />
                <ListViewItem Content="list 2 Item 5" />
                <ListViewItem Content="list 2 Item 6" />

            </ListView>
            <Label Content="List number three" />
            <ListView>
                <ListViewItem Content="list 3 Item 1" />
                <ListViewItem Content="list 3 Item 2" />
                <ListViewItem Content="list 3 Item 3" />
                <ListViewItem Content="list 3 Item 4" />
            </ListView>
        </StackPanel>
    </ScrollViewer>

</StackPanel>

And in the windows loaded code behind I have the following line...

Public Class AmultiListTest
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
    SViewer.Height = SViewer.Height - SPheader.ActualHeight
End Sub
End Class

It would be better to not have the code behind and instead deduct the actual value of the header within the XAML but I'm not sure how to do that. This code works for now.


EDIT: A proper solution - without binding the ScrollViewer's Height or setting it in code behind - would look like this:

<Window ... />
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <StackPanel x:Name="SPheader" Grid.Row="0">
            ...
        </StackPanel >
        <ScrollViewer x:Name="SViewer" Grid.Row="1">
            ...
        </ScrollViewer>
    </Grid>
</Window>
Clemens
  • 123,504
  • 12
  • 155
  • 268
Scott
  • 143
  • 1
  • 9
  • 1
    Your code behind replaces the Height binding, so you could as well remove the Binding from your XAML. Besides that, all that binding or code behind stuff is entirely redundant. You should instead use standard WPF layout mechanism. E.g. replace the outer StackPanel by a Grid with two rows (and set the first row's Height to Auto). See my edit. – Clemens Jun 02 '16 at 15:27
  • Thank you for the grid comment. I'm relatively new to WPF and appreciate the input and example. The windows I'm working on are a lot more complex involving multiple sections and controls out the wazoo. A lot of dynamic elements are built on the fly based on user input, hence the stackpanels made this easier to get started. I'll do more research on the use of Grid. – Scott Jun 02 '16 at 15:46