Search code examples
wpfwpf-controls

Having a hard time getting visibility collapsed to behave the way I want


I have a section of my form defined this way:

    <Grid Margin="380,69,10,50" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
            <TextBlock Text="Script Preview" TextWrapping="Wrap" Margin="0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
            <TextBox Style="{StaticResource TxtRoundCorner}" IsReadOnly="True" AcceptsReturn="True" TextWrapping="Wrap" Text="{Binding SelectedScript.Script}" Margin="0,20,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
        </Grid>
        <Grid Grid.Row="1" Visibility="{Binding ShowParmFilled}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
            <TextBlock Text="Script Parameters Filled In" TextWrapping="Wrap" Margin="0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
            <TextBox Style="{StaticResource TxtRoundCorner}" IsReadOnly="True" AcceptsReturn="True" TextWrapping="Wrap" Text="{Binding AfterParmReplace}" Margin="0,20,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
        </Grid>
    </Grid>

Not all scripts have parms, and those that do, the preview is only supposed to show once the parms are filled in. Therefore I have this method to set the visibility values:

        public void SetScriptParmStateDisplay()
    {
        ShowParmInfo = Visibility.Collapsed;
        ShowParmError = Visibility.Collapsed;
        ShowParmFilled = Visibility.Collapsed;
        if (scriptVarErrors.Any())
        {
            ParametersSet = Brushes.Red;
            ShowParmError = Visibility.Visible;
            ShowParmInfo = Visibility.Visible;
        }
        else if (FoundParameters.Any(_ => string.IsNullOrWhiteSpace(_.Value)))
        {
            ShowParmInfo = Visibility.Visible;
            ParametersSet = Brushes.Gold;
        }
        else
        {
            ShowParmInfo = Visibility.Visible;
            ShowParmFilled = Visibility.Visible;
            ParametersSet = Brushes.Black;
        }
    }

I've also tried these two options:

        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

and

    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>

None of the options worked as I hoped. The first always split the space in half. Didn't matter if the lower grid was collapsed or not. The second caused the top text box to be sized according to it's content. The third caused the lower grid to not respect the limits imposed by the window.

What I want is for the top grid to stretch to fill the available space when the bottom grid is collapsed. If the lower grid is visible, then the space is split evenly between the two grids.

At this point I suspect the solution is to bind the heights in the definition and manually control the height.


Solution

  • Height="auto" won't help you at all. You need

    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    

    when bottom grid is visible and

    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="0" />
    </Grid.RowDefinitions>
    

    when bottom grid is collapsed.

    So in practice you need something like:

    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="{Binding SecondRowHeight, Mode=OneWay}" />
    </Grid.RowDefinitions>