WPF 网格 - Auto-sizing 具有最小高度限制

WPF Grid - Auto-sizing with minimum height constraints

背景

我需要一个具有以下布局属性的网格:

  1. 4 行:header、主要内容、sub-content、页脚
  2. header 是不受调整大小影响的静态内容
  3. 主要内容需要填满所有可用的space,最小高度为180
  4. sub-content是一个可以收缩和增长的RTB。 sub-content 可以吃掉一些 main-contents space,但应该始终为 main-content 保留 180 像素。 sub-content 理想情况下应该只占用它需要的最小面积。如果网格中没有太多剩余空间,则 RTB 应停止增长并启用其内部滚动查看器。
  5. 页脚类似于 header,不受调整大小影响的静态内容

问题

sub-content (RTB) 本身 auto-sizing 不适合剩余的 space,垂直 scroll-bar 也未启用。这会导致主要内容下方的任何内容剪裁到 window.

之外

问题

如何让 RichTextBox 缩小以便显示页脚,允许用户滚动浏览隐藏的 RichTextBox 内容,同时允许 RichTextBox 展开如果用户拉伸 window?

您将在下面找到一个 SSCCE,它演示了我正在努力实现的目标以及它导致的问题:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        MinWidth="200" MinHeight="300" Width="200" Height="300">

    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*" MinHeight="180"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="10"/>
        </Grid.RowDefinitions>

        <TextBlock Grid.Row="0" Text="Header" HorizontalAlignment="Center"/>

        <Rectangle Grid.Row="1" Fill="Red"/>

        <RichTextBox Grid.Row="2"
                     VerticalScrollBarVisibility="Visible"
                     Height="Auto"
                     Margin="0,5,0,0"
                     VerticalAlignment="Stretch"
                     BorderBrush="#FF818181"
                     BorderThickness="0.5"
                     Background="#FFEEEEEE"
                     FontSize="14">
            <FlowDocument>
                <List>
                    <ListItem>
                        <Paragraph>Lorem</Paragraph>
                        <Paragraph>IpSum</Paragraph>
                        <Paragraph>Lorem</Paragraph>
                        <Paragraph>IpSum</Paragraph>
                    </ListItem>
                </List>
            </FlowDocument>
        </RichTextBox>

        <TextBlock Grid.Row="3" Text="Footer" HorizontalAlignment="Center"/>

    </Grid>
</Window>

这是 window 处于最小尺寸时的图像:

这是 window 拉伸显示所有图像后的图像:

额外信息

我知道如果我将 sub-content RowDefinition 设置为 * 那么 RichTextBox 可以正常工作, 除了 window 扩展时占用太多空间的事实。我需要这个区域占用与 Auto 一样多的空间,同时表现得像 *.

分而治之

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication2"
        MinWidth="200" MinHeight="300" Width="200" Height="300">
    <Window.Resources>
        <local:HeightConverter x:Key="HeightConverter" />
    </Window.Resources>

    <!--MainGrid-->
    <Grid Name="grid">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

    <!--AlignmentGrid-->
        <Grid Grid.Row="0">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*" MinHeight="180"/>
                <RowDefinition Height="Auto">
                </RowDefinition>
            </Grid.RowDefinitions>
            <TextBlock Name="head" Grid.Row="0" Text="Header" HorizontalAlignment="Center"/>
            <Rectangle Name="rect" Grid.Row="1" Fill="Red"/>
            <RichTextBox Grid.Row="2"
                         VerticalScrollBarVisibility="Visible"
                         Margin="0,5,0,0"
                         VerticalAlignment="Stretch"
                         BorderBrush="#FF818181"
                         BorderThickness="0.5"
                         Background="#FFEEEEEE"
                         FontSize="14">
                <RichTextBox.MaxHeight>
                    <MultiBinding Converter="{StaticResource HeightConverter}">
                        <Binding ElementName="grid" Path="ActualHeight"/>
                        <Binding ElementName="head" Path="ActualHeight"/>
                        <Binding ElementName="rect" Path="ActualHeight"/>
                        <Binding ElementName="foot" Path="ActualHeight"/>
                    </MultiBinding>
                </RichTextBox.MaxHeight>
                <FlowDocument>
                    <List>
                        <ListItem>
                            <Paragraph>Lorem</Paragraph>
                            <Paragraph>IpSum</Paragraph>
                            <Paragraph>Lorem</Paragraph>
                            <Paragraph>IpSum</Paragraph>
                        </ListItem>
                    </List>
                </FlowDocument>
            </RichTextBox>
        </Grid>

    <!--Footer-->
        <TextBlock Name="foot" Grid.Row="1" Text="Footer" HorizontalAlignment="Center"/>
    </Grid>
</Window>

转换器:

public class HeightConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        double gridHeight = (double)values[0];
        double headHeight = (double)values[1];
        double rectHeight = (double)values[2];
        double footHeight = (double)values[3];

        return gridHeight - headHeight - rectHeight - footHeight;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

请注意,为了让转换器提供所需的结果,MainGrid 的高度不得超过 Window 中内容的高度。