【问题标题】:WPF Grid - Auto-sizing with minimum height constraintsWPF Grid - 具有最小高度限制的自动调整大小
【发布时间】:2016-10-15 02:34:46
【问题描述】:

背景

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

  1. 4 行:页眉、主要内容、子内容、页脚
  2. 标题是静态内容,不会真正受到调整大小的影响
  3. 主要内容需要填满所有可用空间,最小高度为 180
  4. 子内容是可以收缩和增长的RTB。该子内容会占用一些主要内容空间,但应始终为主要内容留出 180 像素。理想情况下,子内容应该只占用它需要的最小区域。如果网格中没有多少空间,RTB 应该停止增长,而是启用其内部滚动查看器。
  5. 页脚类似于页眉,静态内容不受调整大小的影响

问题

子内容 (RTB) 不会自动调整大小以适应剩余空间,也不会启用垂直滚动条。这会导致主要内容下方的任何内容都剪辑到窗口之外。

问题

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

您将在下面找到一个 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>

这是窗口最小尺寸时的图像:

这是窗口被拉伸以显示全部时的图像:

额外信息

我知道如果我将子内容RowDefinition 设置为*,那么RichTextBox 工作正常,除了,因为当窗口展开时它占用了太多空间。我需要这个区域占用与Auto 一样多的空间,同时表现得像*

【问题讨论】:

  • 行定义 1 和 2 都需要是 ` * `,但使用百分比(分别像 7* 和 3*)来调用 RTB 中的嵌入式 ScrollViewer。这也应该缓解页脚隐藏问题。您只需要确定要显示的每个百分比(尽管显然保持最小高度值)。
  • 我目前正在使用 8* 和 3*,直到我有更好的解决方案,但根据屏幕尺寸,3* 大于或小于首选尺寸。大屏幕上的基本子内容有很多空白空间可供主内容使用,而复杂的子内容则被限制在一个区域内,而不是使用未使用的主内容空间。
  • 听起来比描述的更形象化,因为我无法描绘意图与结果。我可能只合并高度的最小值和最大值以获得所需的结果。
  • 作为标准,主要内容应该占据大部分空间,但有时,选定的项目可能有很多内容要放入 RichTextBox。在这种情况下,最好有一个更大的子内容区域以避免滚动文本。然而,当屏幕空间有限时,主要内容需要最小尺寸才能生效,这意味着 RichTextBox 应该适合带有滚动条的小区域。在大屏幕空间中,我不希望 RichTextBox 占用太多它不使用的空间。

标签: c# wpf xaml layout expression-blend


【解决方案1】:

分而治之

<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();
    }
}

请注意,为了让 Converter 给出想要的结果,MainGrid 的高度不能超过 Window 中内容的高度。

【讨论】:

  • 我刚刚尝试了您的示例,效果很好。我已将相同的原则应用于我的核心代码库,并且在那里也可以正常工作。当我最初发布这个问题时,我实际上是在寻找一种我可能会错过的内置方式,但这个解决方案可以在没有“hacky”的情况下工作。我喜欢。完全由您决定,但如果您能说明这项工作现在是公共领域的一部分,我将不胜感激,假设您是原作者。
  • 我想不出一个纯 XAML 解决方案,这是我得到的最接近的解决方案。您可以随意使用它。
  • @BlackBox: “如果你能说明这项工作现在是公共领域的一部分,我将不胜感激”——没有人需要明确说明,因为它内置在 Stack Overflow 的用户协议中。用户创作并在此处发布的所有内容(代码和文本)均在允许免费使用的知识共享许可下完成。见stackoverflow.com/help/licensing。非创作内容必须正确归属于原始作者/版权所有者,并且发布者必须确保他们根据可共享条款发布该内容是合法的。
猜你喜欢
  • 2013-07-17
  • 2011-09-22
  • 1970-01-01
  • 2018-09-16
  • 1970-01-01
  • 1970-01-01
  • 2012-01-04
  • 1970-01-01
相关资源
最近更新 更多