Wpf 如何使网格行高度只占用它所需的空间,而且还受其容器中可用空间的约束?
我想要一个页眉,然后在它下面是一个Wpf 如何使网格行高度只占用它所需的空间,而且还受其容器中可用空间的约束?,wpf,layout,Wpf,Layout,我想要一个页眉,然后在它下面是一个ScrollViewer和一个ItemsControl,然后在它下面是一个页脚。比如: <Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="htt
ScrollViewer
和一个ItemsControl
,然后在它下面是一个页脚。比如:
<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>
标题
项目1
项目2
项目3
项目4
项目5
页脚
以上几乎是我想要的,除了中间一排是贪婪的;即使窗户很高,它也会占据尽可能多的空间,将页脚推到窗户底部
如果我将中间行的定义更改为Height=“Auto”
,它将完全占用它所需的空间量,即使空间不可用,因此ScrollViewer
永远不会显示滚动条,如果窗口不够高,页脚将从窗口底部消失
如何使其在窗口高度足以容纳所有内容时,页脚位于项目控件的正下方,但如果窗口高度不够,则滚动查看器
会显示一个滚动条,页脚位于窗口底部
我不一定需要使用网格
,但我也没有找到任何其他面板
可以满足我的要求。例如,页眉设置为DockPanel.Dock=“Top”
、页脚设置为DockPanel.Dock=“Bottom”
的DockPanel
和填充其余部分的项控件的行为完全相同
我还试过其他一些东西:
- 在页脚
TextBlock
上设置VerticalAlignment=“Stretch”
:无更改李>
- 使页脚行
Height=“*”
:仍然不是我想要的;页脚和ItemsControl
具有相同的高度,因此页脚在大多数情况下会占用太多空间,或者如果使窗口非常短,则页脚会从窗口底部脱落
也许有一种更优雅的方式,但至少下面的方法在类似的情况下对我有效。它是关于计算ItemsControl中所有项目的实际高度,并根据需要调整网格的行高度
<Grid ShowGridLines="True" Loaded="Grid_Loaded">
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="36"/>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" Name="middlerow"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0">Header</TextBlock>
<ScrollViewer Name="scv" Grid.Row="1" VerticalScrollBarVisibility="Auto">
<ItemsControl x:Name="items" Height="Auto" VerticalAlignment="Top">
<ItemsControl.Items>
<TextBlock>Item 1</TextBlock>
<TextBlock>Item 2</TextBlock>
<TextBlock>Item 3</TextBlock>
<TextBlock>Item 4</TextBlock>
</ItemsControl.Items>
</ItemsControl>
</ScrollViewer>
<TextBlock Grid.Row="2">Footer</TextBlock>
</Grid>
标题
项目1
项目2
项目3
项目4
页脚
在代码隐藏中:
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
double height = 0;
foreach (var item in items.Items)
{
height += (item as TextBlock).ActualHeight;
}
if (height < scv.ActualHeight)
{
middlerow.MaxHeight = height;
}
}
private void Grid\u已加载(对象发送方、路由目标方)
{
双倍高度=0;
foreach(items.items中的var项)
{
高度+=(项目作为文本块)。实际高度;
}
如果(高度
感谢您提出了如何执行此操作的概念,以及绑定行的MaxHeight
的想法
XAML:
标题
项目1
项目2
项目3
项目4
项目5
页脚
代码隐藏:
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
double height = 0;
foreach (var item in items.Items)
{
height += (item as TextBlock).ActualHeight;
}
if (height < scv.ActualHeight)
{
middlerow.MaxHeight = height;
}
}
导入System.ComponentModel
类主窗口
实现INotifyPropertyChanged
公共事件PropertyChanged为PropertyChangedEventHandler实现INotifyPropertyChanged.PropertyChanged
公共只读属性项最大为双精度
得到
尺寸高度=0.0
尺寸icg=ic.ItemContainerGenerator
对于i=0到ic.Items.Count-1
高度+=DirectCast(icg.ContainerFromIndex(i),FrameworkElement)。实际高度
下一个
返回高度+6.0'6.0以说明边框的大小?不确定:(
结束
端属性
私有子Ic_SizeChanged(发送方作为对象,e作为SizeChangedEventArgs)
如果e.Heights发生了变化
RaiseEvent PropertyChanged(Me,新PropertyChangedEventArgs(“ItemsMaxHeight”))
如果结束
端接头
末级
在这个示例XAML中,我不需要将MaxHeight增加6,但是在我的实际应用程序中,如果我不增加一点额外的内容,ScrollViewer
总是显示一个可以滚动一点的滚动条。不确定是什么原因导致了这种差异。在发布我的问题后,我环顾四周,发现了更多的问题。这个答案更复杂,并且似乎对窗口上的其他控件的影响非常敏感。例如,它有一个神奇的数字“50或大约窗口标题栏大小的东西”。我怀疑如果要在网格上方添加另一个控件,则需要更改50。但是,我确实喜欢使用绑定,因此它会在需要时更新。您的解决方案简单得多,但它假设ItemsControl
中的项都是TextBlock
s。在我的示例中,我只是填充了ItemsControl
使用TextBlock
s,但在我的实际应用程序中,它是数据绑定的,并使用DataTemplate
生成实际的可视控件。Items
集合有我的数据对象,没有ActualHeight
属性。但是,我找到了ItemContainerGenerator
,它似乎解决了这个问题.我已经发布了一个答案,有点结合了你的解决方案和马库斯的另一个问题。