我正在开发一个 WPF应用程序,其中我有一个带网格的ScrollViewer(16个ColumnDefinitions全部自动宽度),并为每列分配一个图像.我想要创建的效果是当鼠标进入ScrollViewer左侧的区域时,图像将向左
这是我的代码……
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
如果我从Expressions Blend运行它,项目构建正常并显示,但滚动操作不起作用.
如果我从Visual Studio运行它我得到一行错误…
svImages.ScrollToHorizontalOffset(svImages.HorizontalOffset - 0.1)
说用户代码未处理InvalidOperationException …调用线程无法访问此对象,因为另一个线程拥有它.在窗口加载之前我收到此错误.
我哪里出错了.
错误“调用线程无法访问此对象,因为另一个线程拥有它.”是WinForms和WPF控件的标准.在WPF和WinForms中,窗口使用一个特定的线程(通常称为UI线程)在屏幕上呈现.有关控件的每个更新/更改操作都应该在该线程上进行以获得成功.
通常使用WinForms的方法是创建一个特殊的委托并调用Control.Invoke,如此link所示.
从WPF开始,使用Dispatcher也可以达到同样的效果.您的代码应如下所示:
this.Dispatcher.Invoke( () => svImages.ScrollToHorizontalOffset(svImages.HorizontalOffset - 0.1));
更新:
我有以下代码在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)
更新2
代码已更改为问题.
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