How to make WrapPanel to show vertical scrollbar when children are full with or without ScrollViewer
The idea in WPF is that every component has only its own job and if you want certain behavior, you combine multiple components to create the view you are looking for.
This means that in order to get a scroll bar for a panel, you will have to wrap it in a ScrollViewer
component. That’s the purpose of the ScrollViewer
and that’s the only (sane) solution to solve this.
However, though I set the verticalscroll to auto, the verticalscrollbar is always shown even when the Wrappanel doesn't have any child […]
Then you seem to be using the ScrollViewer
incorrectly, or wrapping the wrong element. It should look like this:
<ScrollViewer VerticalScrollBarVisibility="Auto">
<WrapPanel>
<!-- Any number of components here -->
</WrapPanel>
</ScrollViewer>
If I place lots of example labels inside that, then I do get a scroll bar as soon as the window is not large enough to show them all. But if there is enough room, the scroll bar is not displayed.
Note that the ScrollViewer
itself needs to have the proper dimensions in the parent element, so make sure that it’s not larger than the visible area. It is also necessary for the WrapPanel
(or whatever other element you wrap with the ScrollViewer
) to have auto widths and heights. Otherwise, with fixed dimensions, the dimensions of the panel will not change as you modify the panel’s content and as such the scrolling status will not change.
See this complete example with a dynamic number of elements:
<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>
Code-behind:
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);
}
}