He creado una aplicación de muestra:

<Window x:Class="WpfApplication1.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:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="525">
  <Window.Resources>
    <local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
  </Window.Resources>
    <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition /> <!-- Height="Auto" -->
      <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TextBox Grid.Row="0" Text="Some Header Text" />
    <Grid Grid.Row="1">
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
      </Grid.RowDefinitions>
      <CheckBox Grid.Row="0" x:Name="switch" Content="Switch" IsChecked="True" />
      <ListView Grid.Row="1" Visibility="{Binding Path=IsChecked, ElementName=switch, Converter={StaticResource BooleanToVisibilityConverter}}" >
        <ListViewItem Content="11111111"/>
        <ListViewItem Content="22222222"/>
        <ListViewItem Content="33333333"/>
        <ListViewItem Content="44444444"/>
        <ListViewItem Content="55555555"/>
        <ListViewItem Content="66666666"/>
      </ListView>
      <ListView Grid.Row="2">
        <ListViewItem Content="aaaaaaaa"/>
        <ListViewItem Content="bbbbbbbb"/>
        <ListViewItem Content="cccccccc"/>
        <ListViewItem Content="dddddddd"/>
        <ListViewItem Content="eeeeeeee"/>
        <ListViewItem Content="ffffffff"/>
      </ListView>
    </Grid>
    <TextBox Grid.Row="2" Text="Some Footer Text" />
  </Grid>
</Window>

BooleanToVisibilityConverter convierte true a Visible y false a Collapsed.

Si ejecuto el código tal como está, entonces ambos cuadros de lista están visibles y tienen la misma altura y barras de desplazamiento. Entonces esto es exactamente lo que esperaría. Pero, si desactivo la casilla de verificación, el cuadro de lista superior desaparece, pero la fila no se contraerá.

Cuando agregaría Height="Auto" (en la línea 15), el comportamiento del cuadro de lista superior es el esperado: desaparece y el segundo cuadro de lista "sube". Pero cuando la casilla de verificación está marcada, todos los controles se muestran en su tamaño completo. La parte inferior del segundo cuadro de lista está fuera de la ventana y no hay barras de desplazamiento y el pie de página ya no es visible (ya que está fuera del área de la ventana).

Mi objetivo es tener ambos cuadros de lista visibles con barras de desplazamiento y dejar que el cuadro de lista superior se contraiga por casilla de verificación. ¿Qué estoy haciendo mal?

1
Vadim 14 sep. 2018 a las 13:53

3 respuestas

La mejor respuesta

Hay otro factor en esta situación: la definición de fila con Height="*" ocupa espacio incluso si no hay elementos visibles dentro de esa fila (o incluso ningún elemento). Así es como funciona Grid.

Introduzca otro panel: UniformGrid con 1 columna. UniformGrid otorgará la misma altura a ListViews cuando ambos estén visibles, y dará altura completa a la segunda ListView cuando la primera ListView esté oculta.

<Grid Grid.Row="1">
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <CheckBox Grid.Row="0" x:Name="switch" Content="Switch" IsChecked="True" />
  <UniformGrid Columns="1" Grid.Row="1" >
   <ListView Visibility="{Binding Path=IsChecked, ElementName=switch, Converter={StaticResource BooleanToVisibilityConverter}}" >
    <ListViewItem Content="11111111"/>
    <ListViewItem Content="22222222"/>
    <ListViewItem Content="33333333"/>
    <ListViewItem Content="44444444"/>
    <ListViewItem Content="55555555"/>
    <ListViewItem Content="66666666"/>
   </ListView>
   <ListView>
    <ListViewItem Content="aaaaaaaa"/>
    <ListViewItem Content="bbbbbbbb"/>
    <ListViewItem Content="cccccccc"/>
    <ListViewItem Content="dddddddd"/>
    <ListViewItem Content="eeeeeeee"/>
    <ListViewItem Content="ffffffff"/>
   </ListView>
  </UniformGrid>
</Grid>

Otra alternativa es cambiar la segunda fila ListView y Rowspan cuando la primera ListView colapsa:

<Grid Grid.Row="1">
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <CheckBox Grid.Row="0" x:Name="switch" Content="Switch" IsChecked="True" />
  <ListView Grid.Row="1" Visibility="{Binding Path=IsChecked, ElementName=switch, Converter={StaticResource BooleanToVisibilityConverter}}" >
    <ListViewItem Content="11111111"/>
    <ListViewItem Content="22222222"/>
    <ListViewItem Content="33333333"/>
    <ListViewItem Content="44444444"/>
    <ListViewItem Content="55555555"/>
    <ListViewItem Content="66666666"/>
  </ListView>
  <ListView>
    <ListView.Style>
     <Style TargetType="ListView">
      <Setter Property="Grid.Row" Value="2"/>
      <Style.Triggers>
        <DataTrigger Binding="{Binding Path=IsChecked, ElementName=switch}" Value="False">
          <Setter Property="Grid.Row" Value="1"/>
          <Setter Property="Grid.RowSpan" Value="2"/>
        </DataTrigger>
      </Style.Triggers>
     </Style>
    </ListView.Style>
    <ListViewItem Content="aaaaaaaa"/>
    <ListViewItem Content="bbbbbbbb"/>
    <ListViewItem Content="cccccccc"/>
    <ListViewItem Content="dddddddd"/>
    <ListViewItem Content="eeeeeeee"/>
    <ListViewItem Content="ffffffff"/>
  </ListView>
</Grid>
1
ASh 14 sep. 2018 a las 11:20

Puede usar un Style que establece el Height del RowDefinition en 0 cuando el CheckBox está desmarcado. Prueba esto:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition>
            <RowDefinition.Style>
                <Style TargetType="RowDefinition">
                    <Setter Property="Height" Value="*" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsChecked, ElementName=switch}" Value="False">
                            <Setter Property="Height" Value="0" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </RowDefinition.Style>
        </RowDefinition>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TextBox Grid.Row="0" Text="Some Header Text" />
    <CheckBox Grid.Row="1" x:Name="switch" Content="Switch" IsChecked="True" />
    <ListView Grid.Row="2" Visibility="{Binding Path=IsChecked, ElementName=switch, Converter={StaticResource BooleanToVisibilityConverter}}" >
        <ListViewItem Content="11111111"/>
        <ListViewItem Content="22222222"/>
        <ListViewItem Content="33333333"/>
        <ListViewItem Content="44444444"/>
        <ListViewItem Content="55555555"/>
        <ListViewItem Content="66666666"/>
    </ListView>
    <ListView Grid.Row="3">
        <ListViewItem Content="aaaaaaaa"/>
        <ListViewItem Content="bbbbbbbb"/>
        <ListViewItem Content="cccccccc"/>
        <ListViewItem Content="dddddddd"/>
        <ListViewItem Content="eeeeeeee"/>
        <ListViewItem Content="ffffffff"/>
    </ListView>
    <TextBox Grid.Row="4" Text="Some Footer Text" />
</Grid>
0
mm8 14 sep. 2018 a las 11:51

Su problema aquí es que puede ocultar el ListView, pero no el GridRow circundante. Por lo tanto, ListView está contraído, pero no la fila, que todavía tiene su altura establecida en *.

No puedes ocultar fácilmente GridRows. Eso solo es posible al implementarlo en el código subyacente. No estoy seguro si realmente quieres hacer eso. Aquí sería una explicación sobre cómo hacer esto en el código detrás.

La solución más fácil para usted sería usar un contenedor circundante diferente. Por ejemplo, un StackPanel y establezca un MaximumHeight en su ListViews para que no se muestren todos los elementos. Luego, la Visibilidad contraída funciona como se esperaba.

<Window x:Class="WpfApp1.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:wpfApp1="clr-namespace:WpfApp1"
    mc:Ignorable="d"
    Title="MainWindow" Height="250" Width="525">
<Window.Resources>
    <wpfApp1:BooleanConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition />
        <!-- Height="Auto" -->
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TextBox Grid.Row="0" Text="Some Header Text" />
    <StackPanel Grid.Row="1">
        <CheckBox  x:Name="switch" Content="Switch" IsChecked="True" />
        <ListView  Visibility="{Binding Path=IsChecked, ElementName=switch, Converter={StaticResource BooleanToVisibilityConverter}}" MaxHeight="70">
            <ListViewItem Content="11111111"/>
            <ListViewItem Content="22222222"/>
            <ListViewItem Content="33333333"/>
            <ListViewItem Content="44444444"/>
            <ListViewItem Content="55555555"/>
            <ListViewItem Content="66666666"/>
        </ListView>
        <ListView  MaxHeight="70">
            <ListViewItem Content="aaaaaaaa"/>
            <ListViewItem Content="bbbbbbbb"/>
            <ListViewItem Content="cccccccc"/>
            <ListViewItem Content="dddddddd"/>
            <ListViewItem Content="eeeeeeee"/>
            <ListViewItem Content="ffffffff"/>
        </ListView>
    </StackPanel>
    <TextBox Grid.Row="2" Text="Some Footer Text" />
</Grid>
0
Eike B 14 sep. 2018 a las 11:12