Search code examples
wpfxamllistview

Expandable ListView's height exceed the window height


I have a user control ListView1.xaml which looks something like this:

<Grid>
 <ListView ItemSource="{Binding}">
  ...
 </ListView>
</Grid>

In my window I use this control 3 times. Something like this:

<Grid>
 <Grid.RowDefinitions>
  <RowDefinition Height="*"/>
  <RowDefinition Height="*"/>
  <RowDefinition Height="*"/>
 </Grid.RowDefinitions>
 <Expander Grid.Row="0" VerticalAlignment="Top">
  <local:ListView1 DataContext="{Binding Source1}"/>
 </Expander>
 <Expander Grid.Row="1" VerticalAlignment="Top">
  <local:ListView1 DataContext="{Binding Source2}"/>
 </Expander>
 <Expander Grid.Row="2" VerticalAlignment="Top">
  <local:ListView1 DataContext="{Binding Source3}"/>
 </Expander>
</Grid>

When I set Height="*" for each Grid.Row, it would divide the space into 3 equally. It is taking empty space even when the first 2 tabs are not expanded: enter image description here

If I set Height="auto", it would have what I am looking for: when a tab is collapsed, only the expanded one is taking place: enter image description here

But one problem with Height="auto" is that there is no scrollbar on the ListView because the height of the ListView is expanding beyond the height of the window. How would I be able to keep the expanders behave that way and have scrollbar for each ListView when the content is larger that the window?


Solution

  • I would consider a tabcontrol for this sort of UI.

    Part of the problem is the grid isn't sizing to it's parent when all it's rows are auto.

    If you change from using a grid to a dockpanel then you will get scrollbars.

    When you expand the second expander then you'll have to decide what you want to happen though. You'd have to close the first or recalculate what size you want each to be in code.

    But I think this is a lot closer to usable.

    My minimal reproduction uses listboxes.

    <DockPanel>
        <Expander DockPanel.Dock="Top">
            <ListBox ItemsSource="{Binding IntList}"/>
        </Expander>
        <Expander DockPanel.Dock="Top">
            <ListBox ItemsSource="{Binding IntList}"/>
        </Expander>
        <Expander DockPanel.Dock="Top">
            <ListBox ItemsSource="{Binding IntList}"/>
        </Expander>
    </DockPanel>
    

    And my viewmodel:

    public partial class MainWindowViewModel : ObservableObject
    {
        public List<int> IntList { get; set; } = new();
        public MainWindowViewModel()
        {
            for (int i = 0; i < 300; i++)
            {
                IntList.Add(i);
            }
        }
    

    enter image description here