I am trying to programmatically scroll a ScrollViewer. But my UI hangs as soon as the event fires. If I take out while loop, this problem is gone, but then I do not get the behavior I want.
I am using WPF 4.0
Here is the code:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:System="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d"
x:Class="MyApp.Home"
x:Name="HomePage"
WindowTitle="Home"
FlowDirection="LeftToRight" Foreground="{x:Null}" MinWidth="1100" MinHeight="629" Loaded="HomePage_Loaded" SizeChanged="HomePage_SizeChanged">
<Grid x:Name="LayoutRoot">
<TextBlock HorizontalAlignment="Right" Height="48.806" Margin="0,15,15,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="138.908" FontSize="34.667" FontFamily="/MyApp;component/Fonts/#Calibri" Text="featured." Foreground="#FF333333" d:IsLocked="True"/>
<ScrollViewer Height="215" Margin="-20.648,67.806,-20.648,0" VerticalAlignment="Top" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Disabled" Name="FeaturedScroll" Width="1141.296">
<ListView x:Name="FeaturedList" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</ScrollViewer>
<Rectangle x:Name="Left" Height="215" Width="77.129" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,68,0,0" MouseEnter="Left_MouseEnter" Cursor="Hand" Fill="#00000000" MouseLeave="Left_MouseLeave" />
<Rectangle x:Name="Right" Height="215" Width="77.129" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,68,0,0" MouseEnter="Right_MouseEnter" Cursor="Hand" Fill="#00000000" MouseLeave="Right_MouseLeave" />
</Grid>
</Page>
private void Left_MouseEnter(object sender, MouseEventArgs e) {
ScrollLeft = true;
while (ScrollLeft == true)
FeaturedScroll.ScrollToHorizontalOffset(FeaturedScroll.HorizontalOffset - 1);
}
private void Right_MouseEnter(object sender, MouseEventArgs e) {
ScrollRight = true;
while (ScrollRight == true)
FeaturedScroll.ScrollToHorizontalOffset(FeaturedScroll.HorizontalOffset + 1);
}
private void Left_MouseLeave(object sender, MouseEventArgs e) {
ScrollLeft = false;
}
private void Right_MouseLeave(object sender, MouseEventArgs e) {
ScrollRight = false;
}
You can’t scroll from another thread, but you don’t have to because your can fix the problem with some simple code changes.
As everyone else said you can’t get mouse leave event while the mouse enter event is working, you have to change your code so that the mouse enter event returns immediately (by the way, all events should return immediately, otherwise you program – and in extreme cases the entire system will become non-responsive).
Here are two options you can try:
Add a DispatcherTimer to your class, scroll a fixed amount in the timer’s Tick event, on mouse enter call the timer Start method, on mouse leave call Stop.
Use animations, start scrolling using a DoubleAnimation on mouse enter, stop the animation and check current value on mouse leave
Use RepeatButton, if you scroll a fixed amount on the RepeatButton Click event the event will be called repeatedly while the button is pressed (this changes the behavior a little bit because you have to press the button not just hover over it).
There are probably a lot of other options as well, and non of them involve threading (because multi-threading solution won’t work here)