ItemsControl missing vertical scrollbar - wpf

I have the below ItemsControl which wraps items perfectly but it does not have a vertical scrollbar to see the wrapped items. How can I get the scrollbar to show?
<ItemsControl x:Name="tStack" Grid.Column="0" Grid.Row="1"
ItemsSource="{Binding Shows.View}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
BorderThickness="0.5">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" HorizontalAlignment="Left"
VerticalAlignment="Top"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Viewbox HorizontalAlignment="Left" Height="250">
<Controls1:MyShowsUserControl Padding="10"/>
</Viewbox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

ItemsControl by default does not wrap ItemsPresenter in ScrollViewer so you have to do it manually like so:
<ScrollViewer Grid.Column="0" Grid.Row="1">
<ItemsControl x:Name="tStack" ... >
<!-- .... -->
</ItemsControl>
</ScrollViewer>

Wrap your ItemsControl in a ScrollViewer control.
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsControl ...
</ScrollViewer>
Remember to put the Grid.Column="0" Grid.Row="1" attributes in the ScrollViewer instead of in your ItemControl.

Use ScrollViewer and set the property "VerticalScrollBarVisibility" true.
< ScrollViewer VerticalScrollBarVisibility="Auto">
Here your ItemsControl
< /ScrollViewer>

Related

XAML/WPF - ScrollViewer which has StackPanel inside is not scrolling

I have the following StackPanel inside a ScrollViewer that shows User Control elements Whenever a specific event occurs:
Note: many UserControls might appear in the StackPanel that's why I added a Scrollviewer
<ScrollViewer
VerticalScrollBarVisibility="Auto"
Grid.Row="2"
CanContentScroll="True"
Grid.ColumnSpan="2">
<StackPanel Orientation="Vertical">
<ItemsControl ItemsSource="{Binding UserControls}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<views:UserControl/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
Although, the StackPanel is still going out of range and the scroll bars doesn't show and doesn't work!
I tried fixing the height of both the StackPanel and the ItemsControl but it does't seem to work either...
Window Layout containing the ScrollViewer:
<Grid Margin="0,15,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label
Content="This is a Label"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="5,5,0,0"
FontSize="15"
Grid.Row="0" Grid.ColumnSpan="2">
</Label>
<StackPanel Grid.Row="1" Orientation="Horizontal" Grid.ColumnSpan="2">
<ComboBox
ItemsSource="{Binding Something}"
Text="Confirm with..."
SelectedItem="{Binding Something}"/>
<Button
HorizontalAlignment="Left"
Margin="5"
Content="Add new UserControl"
Command="{Binding Path=AddUserControl}"/>
</StackPanel>
<ScrollViewer
VerticalScrollBarVisibility="Auto"
Grid.Row="2"
CanContentScroll="True"
HorizontalScrollBarVisibility="Auto">
<StackPanel Orientation="Vertical">
<ItemsControl ItemsSource="{Binding UserControls}" Height="300">
<ItemsControl.ItemTemplate>
<DataTemplate>
<views:UserControl/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
</Grid>
Here's my UserControl that is added to the StackPanel Inside the ScrollViewer:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel
Orientation="Horizontal"
Grid.Row="0">
<Button
Name="DeleteFilter"
HorizontalAlignment="Left"
Margin="5"
Content="-"/>
<ComboBox
Margin="5"
IsEditable="False"
IsReadOnly="True"
Width="150"
ItemsSource="{Binding SomeObject}"
DisplayMemberPath="Name"
SelectedItem="{Binding SomeObjectProperty}"/>
<ComboBox
Margin="5"
IsEditable="False"
IsReadOnly="True"
Width="150"
ItemsSource="{Binding AnotherObject}"
DisplayMemberPath="Name"
SelectedItem="{Binding AnotherObjectProperty}"/>
<TextBox
x:Name="Value"
Text="{Binding TextBoxValueString}"
TextAlignment="Center"
Width="100"
Margin="5"
Visibility="{Binding TextBoxVisibility}"/>
</StackPanel>
</Grid>
I'm new to XAML and WPF.
Any Suggestions?
ScrollViewers and StackPanel don't work well together. This is because a StackPanel measures its child elements with infinite horizontal space if its Orientation property is set to Horizontal and infinite vertical space if it is set to Vertical. Please refer to my answer here for more information:
How to scroll the datagrid in stackpanel?
So you should replace the StackPanel with another Panel or remove it altogether:
<ScrollViewer
VerticalScrollBarVisibility="Auto"
Grid.Row="2"
CanContentScroll="True"
HorizontalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding UserControls}" Height="300">
<ItemsControl.ItemTemplate>
<DataTemplate>
<views:UserControl/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
I was able to get it run with this setting:
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
Grid.RowSpan="10">
<StackPanel Orientation="Vertical"
Grid.RowSpan="6"
Name="SPanel"
Margin="0,0,-0.4,1.4"
CanVerticallyScroll="True">
<Border BorderBrush="Black"
BorderThickness="1"
Margin="3"
Grid.Row="0"
Name="ChartHolder0">
<dvc:Chart Cursor="Cross"
Background="#FFFFFCF2" />
</Border>
<Border BorderBrush="Black"
BorderThickness="1"
Margin="3"
Grid.Row="0"
Name="ChartHolder0">
<dvc:Chart Cursor="Cross"
Background="#FFFFFCF2" />
</Border>
<Border BorderBrush="Black"
BorderThickness="1"
Margin="3"
Grid.Row="0"
Name="ChartHolder0">
<dvc:Chart Cursor="Cross"
Background="#FFFFFCF2">
</dvc:Chart>
</Border>
</StackPanel>
</ScrollViewer>
And this is what I get:
Was looking for a fix for this problem and Mishka's answer worked for me.
I don't have enough reputation to comment on an answer, but wanted to say that Background="White" fix from Mishka does work for me on Silverlight (didn't try WPF).
<ScrollViewer Background="White">
<StackPanel Margin="5" Background="White">
Works, if I only put Background on the StackPanel the 5 pixel Margin on the stackpanel doesn't scroll. If I don't put Background on either then both the 5 pixel margin and any margins on controls inside the stackpanel dont scroll.
You are missing a Background for either the StackPanel or ItemsControl(Your choise).
Default Background is Null.
With Background Null, the ScrollViewer doesn't get mouse events for the mouse wheel,
and doesn't scroll.

User Controls Wrapped inside a panel MVVM

I am new to WPF/Xaml and searched for this issue I am facing but found it tough. Requesting some help on this.
I need to display usercontrols (DATABOUND) (horizontally) inside a panel/listview so that they wrap when the width of listview/panel is met, with a vertical scroll bar autoshown (as in figure).
so far I have this code.
<ListView Grid.Row="3"
ItemsSource="{Binding Controls}"
VerticalAlignment="Bottom" Background="{x:Null}" BorderBrush="{x:Null}"
>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,10"></StackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="VerticalContentAlignment" Value="Bottom"/>
<Setter Property="Focusable" Value="False" />
</Style>
</ListView.ItemContainerStyle>
<!--<ListView.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding}" VerticalContentAlignment="Bottom"/>
</DataTemplate>
</ListView.ItemTemplate>-->
</ListView>
I have even tried the below code. Yes, it wraps but no scrollbar appears!
<ItemsControl Grid.Row="3"
Width="100" Height="200"
ItemsSource="{Binding Controls}"
VerticalAlignment="Bottom" Background="{x:Null}" BorderBrush="{x:Null}"
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" Margin="0,0,0,10"></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Note: I am okay with any control that makes this happens. Not necessarily be a listview.
To wrap items you need to set ItemsPanel to WrapPanel, like in second example, but you may need to disable horizontal scrolling on ListView:
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled" .../>
also, if you want to use ItemsControl then ScrollViewer is not part of default Template, like for ListView, so you'll need to wrap in in ScrollViewer
<ScrollViewer Grid.Row="3">
<ItemsControl ...>
<!-- .... -->
</ItemsControl>
</ScrollViewer>
and don't forget to move Grid.Row="3" from ItemsControl definition to ScrollViewer
You were close :-)
Put your listview with a view panel that is a wrapanel inside your scrollviewer.
<ScrollViewer>
<ItemsSource="{Binding Controls}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
You are using Wrap panel so you need to specify the width it supposed to take... since wrappanel is inside a items host control wrap panel itself cannot calculate the width.It will try to take all the width with respective to Orientation (in your case its horizontal)
Here is the sample code with list box as items host... in this code i have binded the wrappanel width to the actual width of the list box so that it will never take more width than the list box and also i disabled the horizontal scrolling which you don't need for horizontal orientation and vertical wrapping
Note: Make sure to change item template before using following code and it will work with all items hosts like ListView, ItemsControl...
<ListBox Width="500" Height="500" Name="listbox" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" Width="{Binding ActualWidth,ElementName=listbox}"></WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Height="100" Width="100">
<TextBlock Text="{Binding}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
For ItemsControl
<ItemsControl Grid.Row="3"
Width="100" Height="200"
ItemsSource="{Binding Controls}"
VerticalAlignment="Bottom" Background="{x:Null}" BorderBrush="{x:Null}"
Name="listbox"
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" Width="{Binding ActualWidth,ElementName=listbox}"></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer x:Name="ScrollViewer" Padding="{TemplateBinding Padding}">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Height="30" Width="30">
<TextBlock Text="{Binding}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Resizeable WPF ListBox / ItemsControl items

I would like to have GridSplitter-like functionality in a WPF ListBox (or ItemsControl). The following code doesn't work but demonstrates what I want to achieve:
<ListBox ItemsSource="{Binding MyCollection}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding MyTextProperty}" Margin="0,0,10,0"/>
<GridSplitter
Width="5"
Background="Red"
HorizontalAlignment="Right"
ResizeBehavior="CurrentAndNext"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Does anyone have an idea on how to implement this?
Why not use ListView GridView? GridView supports resizing columns.

Showing a collection of items inside of a ItemsControl horizontally

Here is the XAML markup:
<ScrollViewer Grid.Column="1" Grid.Row="2" HorizontalScrollBarVisibility="Disabled" Width="990">
<StackPanel Margin="50 0 0 40">
<ItemsControl x:Name="streamList" ItemsSource="{Binding StreamInformations}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10" Orientation="Horizontal" >
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ImageUrl}" Height="60" />
<StackPanel Margin="10 0 0 0" VerticalAlignment="Center">
<TextBlock Foreground="Black" Text="{Binding ChannelName}" FontSize="12" />
<TextBlock Foreground="#999" Text="{Binding PlayerName}" FontSize="10" />
<TextBlock Foreground="#999" Text="{Binding ViewCount}" FontSize="10" />
</StackPanel>
</StackPanel>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
And this is how it looks:
I'd like these items to appear horizontally and flow down when it reaches the edge of the StackPanel.
It seems that currently, each item in my DataContext collection is creating it's own StackPanel, so this isn't what I want.
Any suggestions?
If you change the ItemsPanel template to either a WrapPanel or horizontal StackPanel, you can achieve the effect you are after...
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<!--other stuff here-->
</ItemsControl.ItemTemplate>
</ItemsControl>
In this snippet, the ItemsPanel is set to a WrapPanel oriented horizontally. The ItemTemplate would include the binding and styling you already have...

Why does WrapPanel wrap TextBlocks horizontally but UserControls vertically?

This correctly wraps the TextBlocks horizontally:
<StackPanel DockPanel.Dock="Top" Margin="10" HorizontalAlignment="Left">
<TextBlock Text="Simple WrapPanel:" Margin="0 0 0 5"/>
<WrapPanel Orientation="Horizontal">
<TextBlock Text="one"/>
<TextBlock Text="two"/>
<TextBlock Text="thee"/>
<TextBlock Text="four"/>
</WrapPanel>
</StackPanel>
But this incorrectly wraps my UserControls vertically stacked on top of each other (I want them to be horizontally wrapped like the TextBlocks above):
<StackPanel DockPanel.Dock="Top" Margin="10" HorizontalAlignment="Left">
<TextBlock Text="Simple WrapPanel:" Margin="0 0 0 5"/>
<WrapPanel Orientation="Horizontal">
<ItemsControl ItemsSource="{Binding CustomerViewModels}" Width="Auto" BorderThickness="0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<views:CustomerSimpleItemView />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</WrapPanel>
</StackPanel>
CustomerSimpleItemView:
<UserControl x:Class="TestMvvmExample2341.Views.CustomerSimpleItemView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TextBlock Text="{Binding LastName}" FontWeight="Bold" Width="100"/>
</UserControl>
What do I have to do in my UserControl so that they wrap horizontally?
added: even if I change all widths and heights in the usercontrol to Auto, it still stacks vertically...:
<UserControl x:Class="TestMvvmExample2341.Views.CustomerSimpleItemView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="Auto" Height="Auto">
<TextBlock Text="{Binding LastName}" FontWeight="Bold" Width="Auto" Height="Auto"/>
</UserControl>
In your second sample, try to use the WrapPanel inside a ItemsPanelTemplate for the ItemsControl, otherwise the ItemsControl uses a StackPanel by default and your WrapPanel doesn't do anything as there is nothing to wrap.
<StackPanel DockPanel.Dock="Top" Margin="10" HorizontalAlignment="Left">
<TextBlock Text="Simple WrapPanel:" Margin="0 0 0 5"/>
<ItemsControl ItemsSource="{Binding CustomerViewModels}" Width="Auto" BorderThickness="0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<views:CustomerSimpleItemView />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
This is happening because the ItemsControl, by default uses a StackPanel in vertical orientation to layout it child objects. So the wrap panel is actually only laying out one child which is the ItemsControl. What you wan't to do is set the ItemsControl's ItemsPanel property so that is uses a WrapPanel for layout. Your code would look like this:
<StackPanel DockPanel.Dock="Top"
Margin="10"
HorizontalAlignment="Left">
<TextBlock Text="Simple WrapPanel:"
Margin="0 0 0 5" />
<!-- Note I am removing the WrapPanel that was surrounding the ItemsControl -->
<ItemsControl ItemsSource="{Binding CustomerViewModels}"
Width="Auto"
BorderThickness="0">
<!-- This is the important part. Here we set the ItemsPanel template -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<views:CustomerSimpleItemView />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>

Resources