【问题标题】:How to make WrapPanel to show vertical scrollbar when children are full with or without ScrollViewer如何使 WrapPanel 在有或没有 ScrollViewer 的孩子满时显示垂直滚动条
【发布时间】:2016-06-09 06:31:17
【问题描述】:

我有一个 WrapPanel,按钮以编程方式创建并添加为 WrapPanel 的子项。因此,我想在 WrapPanel 充满按钮(子项)时显示垂直滚动条,以便能够连续添加更多按钮。

如果我们需要显示滚动条,我们必须带上 ScrollViewer 吗?没有ScrollViewer就没有办法了吗?我想要得到的是,因为 WrapPanel 的尺寸很小,所以我希望仅在需要时才显示滚动条(比如充满孩子)。

我的代码很简单,如下所示(WrapPanel 在 Grid 内,Grid 在 TabControl 内)

非常感谢您的卓越表现。

更新:我在网上苦苦寻找解决方案好几天了。我尝试将 WrapPanel 放入 ScrollViewer。但是,虽然我将 VerticalScroll 设置为 auto,但即使 WrapPanel 没有任何子项,也会始终显示垂直滚动条。

此外,当我故意让 WrapPanel 充满子项(按钮)时,ScrollViewer 的垂直滚动条不提供向下滚动的可用性。 WrapPanel 底部的按钮显示剪切等等,我无法向下滚动以查看底部按钮之外的内容。我故意将按钮放置在 WrapPanel 的底线之外。

无论有没有,我都希望仅在需要时显示垂直滚动条(充满子项)。这似乎很容易做到。但是很难让它正常工作。

解决方案:由 Henk Holterman 先生提供

                    <DropShadowEffect/>
                </Button.Effect>
            </Button>
            <WrapPanel x:Name="WrapPanelGreen" HorizontalAlignment="Left" Height="180" VerticalAlignment="Top" Width="232" UseLayoutRounding="True" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
        </Grid>
    </TabItem>
</TabControl>

下面是我的简单代码,它以编程方式制作按钮并添加为 WrapPanel 的子项。

for (int k = 0; k < Overviews.Length; k++)
{
    Button btnoverviewcontent = new Button();

    ToolTip tt = new ToolTip();
    tt.Content = "Press this button if you want to modify or delete.";
    btnoverviewcontent.ToolTip = tt;

    btnoverviewcontent.Cursor = Cursors.Hand;

    SolidColorBrush mySolidColorBrush = new SolidColorBrush();
    mySolidColorBrush.Color = Color.FromArgb(255, 101, 173, 241);
    btnoverviewcontent.Background = mySolidColorBrush;

    btnoverviewcontent.Effect = new DropShadowEffect
    {
        Color = new Color { A = 255, R = 0, G = 0, B = 0 },
        Direction = 315,
        ShadowDepth = 5,
        Opacity = 1
    };

    btnoverviewcontent.Padding = new Thickness(3, 3, 3, 3);
    btnoverviewcontent.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Stretch;
    TextBlock textBlock = new TextBlock()
    {
        Text = Overviews[k],
        TextAlignment = TextAlignment.Left,
        TextWrapping = TextWrapping.Wrap,

    };

    btnoverviewcontent.Content = textBlock;
    btnoverviewcontent.BorderThickness = new Thickness(0, 0, 0, 0);
    btnoverviewcontent.FontStretch = FontStretches.UltraExpanded;
    btnoverviewcontent.Margin = new Thickness(5, 5, 5, 5);

    WrapPanelGreen.Children.Add(btnoverviewcontent);
    btnoverviewcontent.Click += new RoutedEventHandler(OnOverviewClick);

【问题讨论】:

  • 我会引导你到:stackoverflow.com/a/2119243/1723823 这是对 WrapPanel 基本功能的很好的细分,其中包含一些关于如何使用它实现滚动的 cmets。
  • @HenkHolterman,请查看我更新的问题。感谢您的宝贵意见。
  • @TernaryTopiary,非常感谢您的指导。但是,我也评估了链接页面,并在此时再次全面评估。我的问题是儿童(按钮)是以编程方式制作的,儿童的大小根据他们的文本内容而有所不同。因此,我不能采用第二种解决方案。请参阅我更新的问题。

标签: c# wpf scroll wrappanel


【解决方案1】:

WPF 中的理念是每个组件都有自己的工作,如果您想要特定的行为,您可以组合多个组件来创建您正在寻找的视图。

这意味着为了获得面板的滚动条,您必须将其包装在 ScrollViewer 组件中。这就是 ScrollViewer 的目的,也是解决这个问题的唯一(理智)解决方案。


但是,尽管我将垂直滚动设置为自动,但即使 Wrappanel 没有任何子项,也会始终显示垂直滚动条 […]

那么您似乎错误地使用了ScrollViewer,或者包装了错误的元素。它应该是这样的:

<ScrollViewer VerticalScrollBarVisibility="Auto">
    <WrapPanel>
        <!-- Any number of components here -->
    </WrapPanel>
</ScrollViewer>

如果我在其中放置大量示例标签,那么只要窗口不够大而无法全部显示,我就会得到一个滚动条。但是如果有足够的空间,滚动条就不显示了。

请注意,ScrollViewer 本身需要在父元素中具有适当的尺寸,因此请确保它不大于可见区域。 WrapPanel(或您使用ScrollViewer 包装的任何其他元素)也必须具有自动宽度和高度。否则,在固定尺寸的情况下,面板的尺寸不会随着您修改面板的内容而改变,因此滚动状态也不会改变。


查看这个包含动态元素数量的完整示例:

<Window x:Class="WpfExampleApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="300" Width="200">
    <ScrollViewer VerticalScrollBarVisibility="Auto">
        <WrapPanel Name="panel">
            <Button Click="Button_Click">Add child</Button>
        </WrapPanel>
    </ScrollViewer>
</Window>

代码隐藏:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Label element = new Label() { Content = "This is some example content" };
        panel.Children.Add(element);
    }
}

【讨论】:

  • 我要指出 WrapPanel 确实已经有一个 ScrollViewer 组件,但我在 Visual Studio 中玩过,得出的结论是,即使你强制它显示滚动查看器一直(通过 WrapPanel 的 XAML 标签:ScrollViewer.VerticalScrollBarVisibility="Visible",它实际上并没有为最终用户提供滚动。我同意这个答案。
  • @TernaryTopiary 附加属性ScrollViewer.VerticalScrollBarVisibility 可以附加到每个组件,但仅对实际具有滚动条的控件有效(例如ListViews)。面板通常不包含任何滚动功能,而仅提供各种布局功能,因此必须始终将它们包裹在 ScrollViewer 中。
  • @poke,非常感谢您的宝贵回答。我也尝试像你的建议一样包装,但随着我的更新,孩子们是以编程方式制作的,并设置为 Wrappanel 的孩子。这与您的建议不同吗?我的滚动条即使在不需要时也会显示,并且在需要时不起作用..哦..上帝..我试图找到解决方案几天,最后要求stackoverflow ...
  • @KayLee 无论元素如何添加到WrapPanel,WPF 都会在每次内容更改时自动重绘控件并重新评估滚动条状态。我在我的答案中添加了一个更完整的示例。如果您仍有问题,请使用您当前的代码扩展您的问题。
  • @HenkHolterman,哦....我按照您的建议将 Wrappanel 的高度和宽度设置为自动(未指定数字)。它运行良好,正如我们所愿。但是,我很遗憾您没有建议作为答案。非常感谢您和 Poke 先生。
【解决方案2】:

...以防有人在 4.5 年后看到这篇文章并觉得该解决方案根本没有帮助: 我有一个类似的问题,这是由我的 ScrollViewer 和动态按钮放入的 StackPanel 引起的...... 似乎 StackPanel 无限扩展了高度,因此 ScrollViewer 和 WrapPanel 总是将它们的高度扩展到窗口边界之外。所以你根本无法滚动。将 StackPanel 包装到 ScrollViewer 对我来说很有帮助(尽管最终我不得不更改控件......)

问候

【讨论】:

  • 今年是 2020 年,如果堆栈面板暴露了滚动条的属性,它仍然感觉应该处理自己的滚动。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-16
  • 1970-01-01
  • 1970-01-01
  • 2012-09-12
  • 2010-10-24
相关资源
最近更新 更多