WPF 网格 - Auto-sizing 具有最小高度限制
WPF Grid - Auto-sizing with minimum height constraints
背景
我需要一个具有以下布局属性的网格:
- 4 行:header、主要内容、sub-content、页脚
- header 是不受调整大小影响的静态内容
- 主要内容需要填满所有可用的space,最小高度为180
- sub-content是一个可以收缩和增长的RTB。 sub-content 可以吃掉一些 main-contents space,但应该始终为 main-content 保留 180 像素。 sub-content 理想情况下应该只占用它需要的最小面积。如果网格中没有太多剩余空间,则 RTB 应停止增长并启用其内部滚动查看器。
- 页脚类似于 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 中内容的高度。
背景
我需要一个具有以下布局属性的网格:
- 4 行:header、主要内容、sub-content、页脚
- header 是不受调整大小影响的静态内容
- 主要内容需要填满所有可用的space,最小高度为180
- sub-content是一个可以收缩和增长的RTB。 sub-content 可以吃掉一些 main-contents space,但应该始终为 main-content 保留 180 像素。 sub-content 理想情况下应该只占用它需要的最小面积。如果网格中没有太多剩余空间,则 RTB 应停止增长并启用其内部滚动查看器。
- 页脚类似于 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 中内容的高度。