父级控件应该控制ScrollViewer的滚动而不是子级控件的ScrollViewer。

6

我有这个:

<Window x:Class="ScrollTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Height="450"
        Width="525">
    <ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Visible"
                  ScrollViewer.VerticalScrollBarVisibility="Visible">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

            <GroupBox Grid.Row="0"
                      Header="Stuff"
                      Height="200">
                <TextBlock Text="Lots of controls go here"
                           HorizontalAlignment="Center"
                           VerticalAlignment="Center" />
            </GroupBox>
            <TabControl Grid.Row="1">
                <TabItem Header="Main Tab">
                    <TextBox MinHeight="100"
                             HorizontalAlignment="Stretch"
                             VerticalAlignment="Stretch"
                             HorizontalContentAlignment="Left"
                             VerticalContentAlignment="Top"
                             ScrollViewer.HorizontalScrollBarVisibility="Visible"
                             ScrollViewer.VerticalScrollBarVisibility="Visible"
                             AcceptsReturn="True" />
                </TabItem>
            </TabControl>
        </Grid>
    </ScrollViewer>
</Window>

当我在TextBox中添加了过多的行,TextBoxScrollViewer没有被使用,而是整个盒子被拉伸并使用最外层的ScrollViewer。我能否在不修复TextBoxTabControl的高度的情况下防止这种情况发生?
更新:
如果我删除TextBoxMinHeight并将MaxLines设置为5,我会得到以下结果: MinHeight removed and MaxLines set to 5 如果我添加了第六行,TextBoxScrollViewer滚动条将被使用,但它们仍然垂直居中于TextBox控件中。
3个回答

1

尝试查看MaxLinesMinLines属性。

来自上面的链接:

如果可见行数超过MaxLines指定的限制,则设置此属性会导致文本框调整大小。此属性仅适用于可见行,不限制实际行数。根据其配置,文本框可能包含额外的非可见行,可以通过滚动访问。如果在TextBox上显式设置了Height属性,则忽略MaxLines和MinLines属性值。

尝试更改:

<TextBox MinHeight="100" 
         HorizontalAlignment="Stretch" 
         VerticalAlignment="Stretch" 
         ...

<TextBox MinLines="5" 
         MaxLines="5"
         HorizontalAlignment="Stretch" 
         VerticalAlignment="Stretch"

编辑:试试这个。它设置了TabItemVerticalContentAlignment。这将使文本框保持在Tab的顶部,我还将最大行数设置为可用区域所能容纳的数量,如果您调整表单大小,您可能需要调整该数字以使用所有可用空间。

<TabItem Header="Main Tab" VerticalContentAlignment="Top"  >
     <TextBox 
              ScrollViewer.HorizontalScrollBarVisibility="Visible"   
              ScrollViewer.VerticalScrollBarVisibility="Visible" 
              MinLines="8"
              MaxLines="8"
              HorizontalAlignment="Stretch"   
              VerticalAlignment="Stretch" 
              HorizontalContentAlignment="Stretch"  
              VerticalContentAlignment="Stretch"  
              AcceptsReturn="True" />
</TabItem>

编辑:

经过进一步调查,TextBox上没有显示滚动条的原因是因为TabControlTabItem正在调整大小以适应TextBox的大小。需要做的是在TabControlTabItemTextBox上设置限制高度,这将允许ScrollViewerTextBox工作。


好主意,但它没有产生任何影响。 - mbursill
@mbursill它有限制高度吗?它应该根据您设置的值增加行数。 - Mark Hall
移除MinHeight产生了奇怪的结果。TextBox保持在*高度(TabItem内容的高度,就像我想要的那样),但是包含在TextBox内部的ScrollViewer被调整为5行并垂直居中。文本插入点与ScrollViewer的行对齐。我会尝试更新问题并附上屏幕截图。 - mbursill
您更新的代码已经接近我想要的效果,但是我希望TextBox的高度能够随着TabItem的高度自适应。Min/Max行会根据行高限制TextBox的高度。我可以看到这对许多布局都有好处,但不适用于我的情况。 - mbursill
我的问题使用了一个固定的高度来证明概念。在我的“真实”项目中,GroupBox 包含许多行(大约 10 行)的网格。无论哪种方式,将 GroupBox 包装在 ScrollViewer 中都无法滚动。当窗口大小调整时,或者输入了许多文本行时,GroupBox 的高度永远不会改变(也不应该改变),因此那些滚动条永远不会显示。 - mbursill
显示剩余2条评论

1
我能够接近这个:
<Window x:Class="ScrollTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Width="525">
    <ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Visible"
                  x:Name="Base">
        <Grid Height="{Binding ElementName=Base, Path=ActualHeight, Mode=OneWay}"
              MinHeight="400">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

            <GroupBox Grid.Row="0"
                      Header="Stuff"
                      Height="200">
                <TextBlock Text="Lots of controls go here"
                           HorizontalAlignment="Center"
                           VerticalAlignment="Center" />
            </GroupBox>
            <TabControl Grid.Row="1">
                <TabItem Header="Main Tab">
                    <Grid x:Name="myInnerGrid">
                        <TextBox MinHeight="100"
                                 MaxHeight="{Binding ElementName=myInnerGrid, Path=ActualHeight, Mode=OneWay}"
                                 HorizontalAlignment="Stretch"
                                 VerticalAlignment="Stretch"
                                 HorizontalContentAlignment="Left"
                                 VerticalContentAlignment="Top"
                                 ScrollViewer.HorizontalScrollBarVisibility="Visible"
                                 ScrollViewer.VerticalScrollBarVisibility="Visible"
                                 AcceptsReturn="True" />
                    </Grid>
                </TabItem>
            </TabControl>
        </Grid>
    </ScrollViewer>
</Window>

请注意外部网格的高度绑定表达式以及TextBox上的MaxHeight绑定表达式。

仍然不完美的是,您必须手动设置触发最外层滚动条的MinHeight。这可能是WPF允许的最接近的方式,而无需编写新的网格控件。

灵感来自于这里: http://social.msdn.microsoft.com/Forums/en/wpf/thread/7b4b0c88-6b8f-4f07-aa8b-8e7018762388


0

我发现解决这个问题的最佳方法是使用在这里概述的Border技巧,垂直和水平都应用。

在下面的示例中,一个ScrollViewer包含一个TextBox,希望TextBox适合所有可用空间(垂直和水平),并且在父ScrollViewer之前垂直滚动。 Border PlaceHolderBorder管理TextBoxWidth,因为父窗口被调整大小。 Border DescriptionPlaceHolderBorder管理Description TextBoxHeight,因为父控件被调整大小,而TextBoxScrollViewer在父控件之前启动。

在占位符Border中有Margin非常重要。

<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Background="{StaticResource ControlBackgroundBrush}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="10"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="10"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Label Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Style="{DynamicResource LabelHeader}" Content="Company" />
        <Label Grid.Row="1" Grid.Column="1" Style="{DynamicResource CompanyNameInput}" Content="{Binding CompanyNameLabel}" />
        <Label Grid.Row="2" Grid.Column="1" Style="{DynamicResource DescriptionInput}" Content="{Binding DescriptionLabel}" />
        <Border Name="PlaceHolderBorder" Grid.Column="2" Margin="7"/>
        <TextBox Grid.Row="1" Grid.Column="2" Text="{Binding CompanyName}" MaxLength="255"/>
        <Border Name="DescriptionPlaceHolderBorder" Grid.Row="2" Margin="7"/>
        <TextBox Grid.Row="2" Grid.Column="2" Text="{Binding Description}" VerticalScrollBarVisibility="Auto"
                 TextAlignment="Left" TextWrapping="Wrap" AcceptsReturn="True" MinHeight="60"
                 Width="{Binding ElementName=PlaceHolderBorder, Path=ActualWidth}"
                 Height="{Binding ElementName=DescriptionPlaceHolderBorder, Path=ActualHeight}"
        />
        <StackPanel Orientation="Horizontal" Grid.Row="3" Grid.Column="2" Margin="5">
            <Button Command="{Binding UpdateCommand}" Content="{Binding UpdateButtonLabel}"></Button>
            <Button Command="{Binding ResetCommand}" Content="{Binding ResetButtonLabel}"></Button>
            <Button Command="{Binding CloseConfirmCommand}" Content="{Binding CloseButtonLabel}"></Button>
        </StackPanel>
    </Grid>
</ScrollViewer>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接