I'm developing a WPF app in which I have a ScrollViewer with grid (16 ColumnDefinitions all auto width) with an image assigned to each column. The effect I want to create is when the mouse enters a area on the left of the ScrollViewer the images will scroll to the left... and when the mouse enters an area on the right of the ScrollViewer they scroll to the right. The scrollbars will be hidden. The areas to the left and right are defined by two rectangles with mouseEnter and mouseLeave events. My code behind utilises a timer to programatically scroll the ScrollViewer leftor right.
Here is my code...
Imports System
Imports System.IO
Imports System.Net
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Data
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Navigation
Partial Public Class Crime
Dim ScrollLeft As Boolean = True
Dim atimer As New System.Timers.Timer()
Public Sub New()
MyBase.New()
Me.InitializeComponent()
' Insert code required on object creation below this point.
' Hook up the Elapsed event for the timer.
AddHandler atimer.Elapsed, AddressOf Me.timer_Tick
atimer.Interval = 100
atimer.Enabled = True
End Sub
'CODE TO SCROLL SCROLLVIEWER PROGRAMATICALLY
Private Sub timer_Tick(sender As Object, e As EventArgs)
If ScrollLeft Then
svImages.ScrollToHorizontalOffset(svImages.HorizontalOffset - 1)
Else
svImages.ScrollToHorizontalOffset(svImages.HorizontalOffset + 1)
End If
End Sub
Private Sub Left_MouseEnter(sender As Object, e As MouseEventArgs)
ScrollLeft = True
atimer.Start()
End Sub
Private Sub Right_MouseEnter(sender As Object, e As MouseEventArgs)
ScrollLeft = False
atimer.Start()
End Sub
Private Sub Left_MouseLeave(sender As Object, e As MouseEventArgs)
atimer.Stop()
ScrollLeft = True
End Sub
Private Sub Right_MouseLeave(sender As Object, e As MouseEventArgs)
atimer.Stop()
End Sub
End Class
If I run this from Expressions Blend the project builds OK and displays, but the scroll action is not working.
If I run this from Visual Studio I get an error with the line...
svImages.ScrollToHorizontalOffset(svImages.HorizontalOffset - 0.1)
saying InvalidOperationException was unhandled by user code... The calling thread cannot access this object because a different thread owns it. I get this error before the window even loads.
Where have I gone wrong.
The error "The calling thread cannot access this object because a different thread owns it." is quite standard for WinForms and WPF controls.
In WPF and WinForms windows are rendered on the screen using one specific thread, usually called UI thread. Every update/change action regarding controls should take place on that thread to have success.
Usual way to go with WinForms is to create a special delegate and call Control.Invoke as shown in this link.
As of WPF, same effect is achieved with the use of a Dispatcher. Your code should look like this:
this.Dispatcher.Invoke( () => svImages.ScrollToHorizontalOffset(svImages.HorizontalOffset - 0.1));
UPDATE:
I've got the following code to work in VB.NET:
Private Delegate Sub ScrollDelegate(ByVal offset As Double)
Private Sub ScrollLeft(ByVal offset As Double)
svImages.ScrollToHorizontalOffset(svImages.HorizontalOffset + offset)
End Sub
// ... calling from background thread
Dim slt As ScrollDelegate
slt = New ScrollDelegate(AddressOf ScrollLeft)
Me.Dispatcher.Invoke(slt)
Update 2
Code changed as to the question.
Dim ScrollLeft As Boolean = True
Dim atimer As New System.Timers.Timer()
Dim scrollMethod As ScrollDelegate
Private Delegate Sub ScrollDelegate(ByVal offset As Double)
// ...
Me.InitializeComponent()
slt = New ScrollDelegate(AddressOf DoScroll)
// ...
Private Sub timer_Tick(sender As Object, e As EventArgs)
If ScrollLeft Then
Me.Dispatcher.Invoke(slt, -1)
Else
Me.Dispatcher.Invoke(slt, 1)
End If
End Sub
// ...
Private Sub DoScroll(ByVal offset As Double)
svImages.ScrollToHorizontalOffset(svImages.HorizontalOffset + offset)
End Sub
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With