如何使scrollviewer在WPF中将高度设置为自动时工作?
我了解到,如果将如何使scrollviewer在WPF中将高度设置为自动时工作?,wpf,xaml,uwp-xaml,scrollviewer,autosize,Wpf,Xaml,Uwp Xaml,Scrollviewer,Autosize,我了解到,如果将ScrollViewer所在的网格行的高度设置为Auto,垂直滚动条将不会生效,因为ScrollViewer的实际大小可能大于可见高度。因此,为了使滚动条工作,我应该将高度设置为固定数字或星形高度 但是,我现在有这个要求,我有两个不同的视图位于两个网格行中,我有一个切换按钮在这两个视图之间切换:当一个视图显示时,另一个视图隐藏/消失。所以我定义了两行,两个高度都设置为Auto。我将每行视图的可见性绑定到ViewModel中的布尔属性(一个从True转换为Visible,另一个从T
ScrollViewer
所在的网格行的高度设置为Auto
,垂直滚动条将不会生效,因为ScrollViewer
的实际大小可能大于可见高度。因此,为了使滚动条工作,我应该将高度设置为固定数字或星形高度
但是,我现在有这个要求,我有两个不同的视图位于两个网格行中,我有一个切换按钮在这两个视图之间切换:当一个视图显示时,另一个视图隐藏/消失。所以我定义了两行,两个高度都设置为Auto
。我将每行视图的可见性绑定到ViewModel中的布尔属性(一个从True
转换为Visible
,另一个从True
转换为Collapsed
。其思想是当一个视图的可见性为Collapsed
时,网格行/视图的高度将自动更改为0
视图show/hidden运行良好。但是,在一个视图中,我有一个
ScrollViewer
,正如我所提到的,当行高度设置为Auto
时,它不起作用。有人能告诉我如何在仍然让ScrollViewer
自动工作的情况下满足这些要求吗?我想我可以在代码中设置高度ind.但由于我使用的是MVVM,因此需要额外的通信/通知。有没有更直接的方法来实现这一点?如果可以的话,将高度从Auto
更改为*
例如:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="525">
<StackPanel Orientation="Horizontal" Background="LightGray">
<Grid Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Auto" x:Name="_scroll1">
<Border Height="300" Background="Red" />
</ScrollViewer>
<TextBlock Text="{Binding ElementName=_scroll1, Path=ActualHeight}" Grid.Row="1"/>
</Grid>
<Grid Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Auto" x:Name="_scroll2">
<Border Height="300" Background="Green" />
</ScrollViewer>
<TextBlock Text="{Binding ElementName=_scroll2, Path=ActualHeight}" Grid.Row="1"/>
</Grid>
</StackPanel>
</Window>
< /代码> 你可以在ScLoVIEVIEW上设置一个固定的高度,但是你必须考虑到你的网格的第二行也会有这个高度,因为行的第一个孩子将是ScRelVIEW和行的高度是Autoor,或者你把ScRelVIEW的高度绑定到你的布局中的另一个控件上。我们不知道你的布局看起来如何。
最后,如果您不喜欢这两个选项,只需按照swiszcz的建议将行的高度设置为*或hack wpf编写您自己的自定义面板,该面板将能够在每个平行宇宙或类似的情况下布局所有可能的内容。:)在MVVM中,我的工作方式是将ScrollViewer
的高度绑定到父控件的ActualHeight
(始终为UIElement
类型)
ActualHeight
是一个只读属性,只有在将控件绘制到屏幕上后才能设置。如果调整窗口大小,它可能会更改
<StackPanel>
<ScrollViewer Height="{Binding Path=ActualHeight,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UIElement}}">
<TextBlock Text=Hello"/>
</ScrollViewer>
</StackPanel>
附录B:以前的尝试2
有用信息:请参阅
如果什么都不起作用,那可能是因为父级的实际高度
要么是0(因此没有可见的内容)要么是巨大的(因此scrollviewer永远不需要出现)。如果网格嵌套较深,且scrollviewer位于底部,则问题更大
- 使用Snoop查找父级
StackPanel
的ActualHeight
。在属性中,按单词“Actual”
进行过滤,这将返回ActualHeight
和ActualWidth
- 如果
实际高度
为零,则使用最小高度
给它一个最小高度,这样我们至少可以看到一些东西
- 如果
实际高度
太大以至于超出屏幕边缘(即16000),请使用最大高度
为其设定一个合理的最大高度,这样就会出现滚动条
滚动条出现后,我们可以进一步清理:
- 将
堆叠面板
或网格
的高度
绑定到父级的实际高度
最后,将一个ScrollViewer
放在StackPanel
内
附录C:以前的尝试3
事实证明,这有时会失败:
Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel}}"
原因?如果绑定失败,那么高度将为零,并且什么也看不到。如果绑定到不可访问的元素,则绑定可能失败。如果我们向上移动可视化树,然后向下移动叶节点,则绑定将失败(例如,向上到父网格,然后向下到附加到该网格的行的实际高度
)。这就是为什么绑定到行定义的实际宽度
根本不起作用的原因
附录D:先前的尝试4
最后,我通过确保所有父元素的Height=Auto
都是用户控件中的第一个
元素来实现这一点。我发现,您必须将您的ScrollViewer
放在一个具有Height=Auto
的容器中,或者您可以得到其父元素的高实际大小e
并将其应用于该容器
在我的例子中,我有UserControl
like
<Grid Margin="0,0,0,0" Padding="0,2,0,0">
<ScrollViewer Height="Auto" ZoomMode="Disabled" IsVerticalScrollChainingEnabled="True" VerticalAlignment="Top"
HorizontalScrollMode="Enabled" HorizontalScrollBarVisibility="Disabled"
VerticalScrollMode="Enabled" VerticalScrollBarVisibility="Visible">
<ListView ItemsSource="{x:Bind PersonalDB.View, Mode=OneWay}" x:Name="DeviceList"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ItemTemplate="{StaticResource ContactListViewTemplate}"
SelectionMode="Single"
ShowsScrollingPlaceholders="False"
Grid.Row="1"
Grid.ColumnSpan="2"
VerticalAlignment="Stretch"
BorderThickness="0,0,0,0"
BorderBrush="DimGray">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel AreStickyGroupHeadersEnabled="False" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate x:DataType="local1:GroupInfoList">
<TextBlock Text="{x:Bind Key}"
Style="{ThemeResource TitleTextBlockStyle}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</ScrollViewer>
</Grid>
请注意,行的高度
为*
当我填充ContentControl
时,我在Loaded
事件中使用此代码
UIControlContainer.Content = new UIDeviceSelection() {
VerticalAlignment = VerticalAlignment.Stretch,
HorizontalAlignment = HorizontalAlignment.Stretch,
Height = UIControlContainer.ActualHeight,
Width = UIControlContainer.ActualWidth
};
而且当ContentControl
更改其大小时,您必须更新UserControl
的大小
UIControlContainer.SizeChanged += UIControlContainer_SizeChanged;
private void UIControlContainer_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (UIControlContainer.Content != null)
{
if (UIControlContainer.Content is UserControl)
{
(UIControlContainer.Content as UserControl).Height = UIControlContainer.ActualHeight;
(UIControlContainer.Content as UserControl).Width = UIControlContainer.ActualWidth;
}
}
}
享受吧
<> P.S.Access,我为UWP做了。 < P>我遇到了类似的问题,花了我几个小时来找出解决方案。解决的问题是使用DokPad作为父容器而不是堆栈面板。只要功能类似于垂直StAdPosik,就指定所有的孩子要停靠在顶部。考虑使用LaSTaStHealth=“false”。在Dock XAML中,这是默认值
因此,不是:
SomeTextBox
谢谢你的回复。但是我不太理解你的回答
UIControlContainer.Content = new UIDeviceSelection() {
VerticalAlignment = VerticalAlignment.Stretch,
HorizontalAlignment = HorizontalAlignment.Stretch,
Height = UIControlContainer.ActualHeight,
Width = UIControlContainer.ActualWidth
};
UIControlContainer.SizeChanged += UIControlContainer_SizeChanged;
private void UIControlContainer_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (UIControlContainer.Content != null)
{
if (UIControlContainer.Content is UserControl)
{
(UIControlContainer.Content as UserControl).Height = UIControlContainer.ActualHeight;
(UIControlContainer.Content as UserControl).Width = UIControlContainer.ActualWidth;
}
}
}