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

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.

Related

VirtualizingPanel.ScrollUnit="Pixel" doesnt work and change scrolling to smooth for listbox in .NET 4.7.2 wpf

I am interested in smooth (pixel) scrolling of ListBox but I don't want to use ScrollViewer.CanContentScroll="False" because it does not allow to virtualise ListBox view. I have read that starting by .NET 4.5 it is possible to use VirtualizingPanel.ScrollUnit="Pixel" which allows both virtualising and smooth scrolling, however it doesn't change the behaviour of my scrolling
Here is the code of the listBox (orientation is horizontal)
<ListBox Name="FilmsListBox" Grid.Row="1" Margin="50 25 50 30" HorizontalAlignment="Center" ScrollViewer.HorizontalScrollBarVisibility="Visible" VirtualizingPanel.ScrollUnit="Pixel" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ScrollViewer.CanContentScroll="True" Background="Transparent" BorderBrush="Transparent" Style="{DynamicResource TransparentListBox}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" Margin="30" Width="125" Height="200" VerticalAlignment="Top" HorizontalAlignment="Stretch">
<Border BorderThickness="1.2" BorderBrush="#FF715C4E">
<Image Name="FilmPosterImage" Stretch="UniformToFill" Source="Images/eternals_default.jpg"></Image>
</Border>
</DockPanel>
<TextBlock Grid.Row="1" Margin="10 0 10 25" TextWrapping="Wrap" TextAlignment="Center" HorizontalAlignment="Center" Name="FilmTitleTextBlock" FontFamily="Calibri" FontSize="22" Initialized="FilmTitleTextBlock_Initialized">Вечные (18+)</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Please help with some alternatives or explain why the expected tool as VirtualizingPanel.ScrollUnit doesn't behave properly

Why ScrollViewer overrides Grid row height in wpf?

I have a ScrollViewer which contains a Grid having two rows of height '*'
<ScrollViewer>
<Grid HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" Grid.Column="0"
Header="XYZ"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Margin="0,10,0,0"
Width="Auto" MinWidth="160"
BorderThickness="0"
Style="{StaticResource MyGroupBoxStyle}">
<ListBox Name="lstMentorGroups" IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=MyCollection}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Style="{StaticResource MyListBoxStyle}">
<ListBox.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
<GroupBox Grid.Row="1" Grid.Column="0" MinWidth="160"
Header="ABC" Margin="0,10,0,0"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
BorderThickness="0"
Style="{StaticResource MyGroupBoxStyle}">
<ListBox ItemsSource="{Binding Path=List1, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Style="{StaticResource MyListBoxStyle}" Margin="0,0,5,0">
<ListBox.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding Path=Prop1}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
</Grid>
</ScrollViewer>
But at run time 1st Group box gets full height needed by its containing listbox that means it overrides Grid height * to auto
It works fine if I don't use scrollviewer it gives 50-50% height to each groupbox.
You need set the Height of the Grid if it's in the ScrollViewer, otherwise the Grid will have as much Height as it need, which means the ListBox in the Grid will get unlimited Height to display its items.
To ensure that the both rows takes the same height you should use the SharedSizeGroupe
So what you should do is:
<ScrollViewer>
<Grid HorizontalAlignment="Stretch" Grid.IsSharedSizeScope="True">
<Grid.RowDefinitions>
<RowDefinition SharedSizeGroup="A" />
<RowDefinition SharedSizeGroup="A" />
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" Grid.Column="0"
Header="XYZ"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Margin="0,10,0,0"
Width="Auto" MinWidth="160"
BorderThickness="0"
Style="{StaticResource MyGroupBoxStyle}">
<ListBox Name="lstMentorGroups" IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=MyCollection}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Style="{StaticResource MyListBoxStyle}">
<ListBox.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
<GroupBox Grid.Row="1" Grid.Column="0" MinWidth="160"
Header="ABC" Margin="0,10,0,0"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
BorderThickness="0"
Style="{StaticResource MyGroupBoxStyle}">
<ListBox ItemsSource="{Binding Path=List1, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Style="{StaticResource MyListBoxStyle}" Margin="0,0,5,0">
<ListBox.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding Path=Prop1}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
</Grid>
As Grid is placed in ScrollViewer so it takes whole space how much it's controls requires. And I don't want to show vertical scroll bar.
I just set Grid MaxHeight to ScrollViewer ActualHeight
MaxHeight="{Binding ElementName=ScrollViewer, Path=ActualHeight}"

How i can stretch comboBox in DockPanel

I want to create a status bar with combobox, progress bar and two buttons. At the left it must be progressbar, in the center combobox, that get all available free space and two buttons at the right But I get very little combobox, and dockpanel don't fill status bar..
My Xaml code
<StatusBar DockPanel.Dock="Bottom" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<DockPanel Width="1004" Height="Auto" LastChildFill="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<ProgressBar Name="ExecutionProgress" Height="Auto" Margin="3" MinWidth="200" MaxWidth="400" DockPanel.Dock="Left"></ProgressBar>
<StackPanel Orientation="Horizontal" Height="Auto" DockPanel.Dock="Right">
<Button Name="SaveExecutionLog" Width="Auto" Height="Auto" Content="Save Log" Margin="2" Padding="4"></Button>
<Button Name="ClearExecutionLog" Width="Auto" Height="Auto" Content="Clear Log" Margin="2" Padding="4"></Button>
</StackPanel>
<ComboBox Name="ExecutionEvents" Height="Auto" Width="Auto" Margin="3">
<ComboBoxItem>jfjfjxdfvbdfhfghfghfghfghfghjfg[pjkhlp'fghfg]ophkfg]pkh]pfg]hkfg]pkh]pfghokfg]pkh]-fg</ComboBoxItem>
</ComboBox>
</DockPanel>
</StatusBar>
Where is my mistake? Thank you!
I don't know where was the problem, but i fixed it by changing DockPanel to Grid. It was a magic.

why aren't the buttons aligning horizontally in the stackpanel?

I have a list of buttons being generated from data, so there are a variable number of buttons. In an old version of the software I am overhauling, they used random custom controls but the result was that there was an infinitely growing horizontal scroller.
It appears I have the exact same XAML but it's not aligning each item horizontally, only vertically
<ScrollViewer Background="#33FFFFFF" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled" >
<StackPanel Orientation="Horizontal">
<ItemsControl ItemsSource="{Binding Events}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Margin="10" HorizontalAlignment="Stretch" Background="#FF1B1B1B" BorderThickness="5" BorderBrush="White" Command="{Binding Source={StaticResource Locator}, Path=EventSelector.ViewEventCommand}" CommandParameter="{Binding }">
<Grid Name="tileGridButton" Height="600" Width="400" Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
</Grid.RowDefinitions>
<Border Grid.Row="0" Name="tileImageBorder" Margin="5" BorderThickness="1" VerticalAlignment="Stretch" HorizontalAlignment="Center">
<Image Name="tileImage" Margin="0" Source="{Binding ImageURL}"/>
</Border>
<Grid Grid.Row="1" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="6*"></RowDefinition>
<RowDefinition Height="4*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Name="tileText" Margin="5" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" FontSize="30" FontWeight="Bold" Text="{Binding Title}" />
<TextBlock Grid.Row="1" Name="tileDescription" Margin="5" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" FontSize="25" FontWeight="Bold" Text="{Binding EventTimeBegin}" />
</Grid>
</Grid>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
First of all your StackPanel is pretty much useless because it only contains a single item, the ItemsControl.
Instead you need to change your ItemsControl so that it uses a StackPanel as its method of laying out items inside the ItemsControl...
<ItemsControl ...>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
<ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
.....

ListBox scrolling with variable height

I have a problem with ListBox scrolling. Everytime I have more items than can be shown on screen and I try to scroll through the list it automatically snaps back to the top. I found this can be fixed by setting a fixed height to the ListBox.
However, I need to add items to the list dynamically and hence the height changes.
The Listbox is in the second row of a grid nested in a PivotItem.
How can I either set the height of the Listbox dynamically with XAML or achieve a scrolling effect that does not always snap to the top and hence prevents me from reading/editing items on the bottom?
Here is the XAML:
<Grid x:Name="LayoutRoot">
...
<controls:Pivot Title="Malts">
<controls:PivotItem Header="Gravity" Name="GravityPivot">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid> some more controls in row 0</Grid>
<Grid
Grid.Row="1">
<ListBox
VerticalAlignment="Stretch"
ItemsSource="{Binding ItemList}"
Padding="10,10,0,10"
ItemContainerStyle="{StaticResource ListBoxItemStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock
Style="{StaticResource PhoneTextExtraLargeStyle}"
Text="{Binding Name}"
VerticalAlignment="Bottom"/>
<StackPanel>
<StackPanel
Orientation="Horizontal" >
<TextBlock
Text="{Binding Amount, Converter={StaticResource WeightConverter},StringFormat=' {0:f2}'}"
Margin="10,0,5,0"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock
Text="{Binding ., Converter={StaticResource UnitExtension}, ConverterParameter='Weight'}"
Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
</StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem
Header="Edit"
Command="{Binding ElementName=MaltList, Path=DataContext.EditCommand}"
CommandParameter="{Binding}"/>
<toolkit:MenuItem
Header="Remove"
Command="{Binding ElementName=MaltList, Path=DataContext.RemoveCommand}"
CommandParameter="{Binding}"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
</controls:PivotItem>
Thank you!
Try this, should fix you up;
<ListBox>
<!-- You want this part... -->
<ListBox.Template>
<ControlTemplate>
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
</ListBox>

Resources