如何使网格行高仅占用所需的空间,又受其容器中可用空间的限制? [英] How to have Grid row height take only the space it needs, but also be constrained by available space in its container?

查看:70
本文介绍了如何使网格行高仅占用所需的空间,又受其容器中可用空间的限制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想有一个页眉,然后是在ScrollViewerItemsControl之下,然后是页脚.像这样:

I want to have a header, then below that a ScrollViewer with an ItemsControl, then below that a footer. Something like:

<Window x:Class="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"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid ShowGridLines="True">
        <Grid.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="FontSize" Value="36"/>
            </Style>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0">Header</TextBlock>
        <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
            <ItemsControl>
                <ItemsControl.Items>
                    <TextBlock>Item 1</TextBlock>
                    <TextBlock>Item 2</TextBlock>
                    <TextBlock>Item 3</TextBlock>
                    <TextBlock>Item 4</TextBlock>
                    <TextBlock>Item 5</TextBlock>
                </ItemsControl.Items>
            </ItemsControl>
        </ScrollViewer>
        <TextBlock Grid.Row="2">Footer</TextBlock>
    </Grid>
</Window>

上面几乎是我想要的,除了中间的行是贪婪的;即使窗户很高,它也会占用尽可能多的空间,将页脚推到窗户底部.

The above is almost what I want, except the middle row is greedy; even if the window is very tall, it takes up as much space as it can, pushing the footer to the bottom of the window.

如果我将中间行的定义更改为Height="Auto",则即使该空间不可用,它也会恰好占用其所需的空间量,因此ScrollViewer从不显示滚动条,并且页脚将如果窗户不够高,就会迷失在窗户底部.

If I change the middle row's definition to Height="Auto", it takes up exactly the amount of space that it needs, even if that space isn't available, so the ScrollViewer never shows the scrollbar, and the footer will get lost off the bottom of the window if the window isn't tall enough.

我如何做到这一点,如果窗口足够高,足以容纳所有内容,则页脚位于ItemsControl的正下方,但是如果窗口不够高,ScrollViewer将显示滚动条,并且页脚在窗口的底部?

How do I make it so that if the window is tall enough for everything to fit, the footer is immediately below the ItemsControl, but if the window isn't tall enough, the ScrollViewer shows a scrollbar and the footer is at the bottom of the window?

我不一定需要使用Grid来执行此操作,但是我没有找到其他可以执行我想要的操作的Panel.例如,标头设置为DockPanel.Dock="Top"DockPanel,页脚设置为DockPanel.Dock="Bottom"ItemsControl,填充其余部分的ItemsControl的行为完全相同.

I don't necessarily need to do this with a Grid, but I didn't find any other Panel that would do what I want either. E.g., a DockPanel with the header set to DockPanel.Dock="Top", the footer set to DockPanel.Dock="Bottom", and the ItemsControl filling the rest behaves exactly the same way.

我尝试过的其他一些东西:

Some other stuff I've tried:

  • 在页脚TextBlock上设置VerticalAlignment="Stretch":不变.
  • 使页脚行Height="*":仍然不是我想要的;页脚和ItemsControl的高度相同,因此页脚大部分时间占用太多空间,或者如果您将窗口做得非常短,则它会离开窗口底部.
  • Setting VerticalAlignment="Stretch" on the footer TextBlock: no change.
  • Making the footer row Height="*": still not what I want; the footer and the ItemsControl get the same height, so the footer takes up too much space most of the time, or if you make the window extremely short, it goes off the bottom of the window.

推荐答案

感谢妈妈的答案,其中包括为此,请 Markus的答案,以绑定行的MaxHeight.

Thanks to mami's answer for the concept of how to do this, and Markus's answer for the idea to bind the Row's MaxHeight.

XAML:

<Window x:Class="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"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid ShowGridLines="True">
        <Grid.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="FontSize" Value="36"/>
            </Style>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*" MaxHeight="{Binding ItemsMaxHeight,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0">Header</TextBlock>
        <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
            <ItemsControl Name="ic" SizeChanged="Ic_SizeChanged">
                <ItemsControl.Items>
                    <TextBlock>Item 1</TextBlock>
                    <TextBlock>Item 2</TextBlock>
                    <TextBlock>Item 3</TextBlock>
                    <TextBlock>Item 4</TextBlock>
                    <TextBlock>Item 5</TextBlock>
                </ItemsControl.Items>
            </ItemsControl>
        </ScrollViewer>
        <TextBlock Grid.Row="2">Footer</TextBlock>
    </Grid>
</Window>

后面的代码:

Imports System.ComponentModel

Class MainWindow
    Implements INotifyPropertyChanged

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Public ReadOnly Property ItemsMaxHeight As Double
        Get
            Dim Height = 0.0
            Dim icg = ic.ItemContainerGenerator

            For i = 0 To ic.Items.Count - 1
                Height += DirectCast(icg.ContainerFromIndex(i), FrameworkElement).ActualHeight
            Next

            Return Height + 6.0 ' 6.0 to account for the size of borders? Not sure :(
        End Get
    End Property

    Private Sub Ic_SizeChanged(sender As Object, e As SizeChangedEventArgs)
        If e.HeightChanged Then
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("ItemsMaxHeight"))
        End If
    End Sub
End Class

在此示例XAML中,我不需要将MaxHeight增加6,但是在我的实际应用中,如果我不添加任何额外内容,则ScrollViewer始终显示可以滚动的滚动条.一点点.不确定导致差异的原因.

In this sample XAML, I don't need to increase the MaxHeight by 6, but in my actual app, if I don't add in a little extra, the ScrollViewer always shows a scrollbar that can be scrolled a tiny bit. Not sure what causes the discrepancy.

这篇关于如何使网格行高仅占用所需的空间,又受其容器中可用空间的限制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆