Search code examples
c#wpfvb.netxamlexpander

Can you have an expander do an overlay overtop of other visual tree elements in WPF?


The problem is cosmetic more than a data problem. Is there a simple way to put element of

<Expander>(contents)</Expander>

in a popup or something else to make it just overlay over top the other elements?

XAML: (I just did a simple For loop to populate the binding of the 'Locs' in a ViewModel in the constructor, else most of the VM is blank)

<Window x:Class="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:MVVM"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="800">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid>
      <Expander ExpandDirection="Down" IsExpanded="True" HorizontalAlignment="Stretch">
        <Expander.Header>
          <TextBlock TextAlignment="Left" HorizontalAlignment="Center" VerticalAlignment="Center" Text="LOCATIONS" FontWeight="Bold"/>
        </Expander.Header>
        <ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Auto" Height="300" HorizontalAlignment="Stretch">
          <ItemsControl ItemsSource="{Binding Locs}" >
            <ItemsControl.ItemTemplate>
              <DataTemplate>
                <CheckBox Margin="5" Content="{Binding}" />
              </DataTemplate>
            </ItemsControl.ItemTemplate>
          </ItemsControl>
        </ScrollViewer>
      </Expander>
    </Grid>
    <Label Grid.Row="1" Height="100" Content="Test Content" FontSize="32" />
  </Grid>
</Window>

Start of the Application and looks fine.

Start of Control

Click the Expander and now it collapses, but it jumps text up. I understand in the visual tree this is default behavior but is there a simple way to just wrap this in some overlay like a popup that does not make the other text jump when it collapses?

End of Control


Solution

  • You could set the Height property of the Expander to a fixed value to reserve its vertical space upfront.

    Or you could put the ScrollViewer in a Popup, e.g.:

    <Expander x:Name="expander" ExpandDirection="Down" IsExpanded="True" HorizontalAlignment="Stretch">
        <Expander.Header>
            <TextBlock TextAlignment="Left" HorizontalAlignment="Center" VerticalAlignment="Center" Text="LOCATIONS" FontWeight="Bold"/>
        </Expander.Header>
        <Popup PlacementTarget="{Binding ElementName=expander}"
                       Placement="Bottom"
                       IsOpen="{Binding IsExpanded, ElementName=expander}">
            <ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Auto" Height="300" HorizontalAlignment="Stretch"
                                  Background="White">
                <ItemsControl>
                    <CheckBox Margin="5" Content="1" />
                    <CheckBox Margin="5" Content="2" />
                    <CheckBox Margin="5" Content="3" />
                    <CheckBox Margin="5" Content="4" />
                    <CheckBox Margin="5" Content="5" />
                </ItemsControl>
            </ScrollViewer>
        </Popup>
    </Expander>
    
    <Label Grid.Row="1" Height="100" Content="Test Content" FontSize="32" />
    

    You might want to read this to be able to move the Popup when the Expander moves:

    How can I move a WPF Popup when its anchor element moves?