WPF 使用 Dipatcher 强制 GUI 更新

发布于 2024-09-24 21:47:57 字数 2099 浏览 6 评论 0原文

我只需要显示一个自定义控件(带有旋转指针的时钟)并用它来替换鼠标光标,问题是如果我写:

Me.gridScreen.Visibility = Visibility.Visible
' some operations that takes about 1 second
Me.gridScreen.Visibility = Visibility.Hidden
(gridScreen is the grid that contains the user-control)

显然我什么也看不到,因为 UI 的更新发生在程序。我尝试过 Me.UpdateLayout(),但它不起作用。

我尝试以多种方式使用解包器,但没有一个有效:-(

这是我失败的尝试:

(uCurClock 是用户控件,gridScreen 是放置在窗口顶层的网格,具有透明背景,包含用户控件)

Private Sub showClock()
    Dim thread = New System.Threading.Thread(AddressOf showClockIntermediate)
    thread.Start()
End Sub

Private Sub hideClock()
    Dim thread = New System.Threading.Thread(AddressOf hideClockIntermediate)
    thread.Start()
End Sub

Private Sub showClockIntermediate()
    Me.Dispatcher.BeginInvoke(DispatcherPriority.Normal, _
        New Action(AddressOf showClockFinale))
End Sub

Private Sub hideClockIntermediate()
    Me.Dispatcher.BeginInvoke(DispatcherPriority.Normal, _
        New Action(AddressOf hideClockFinale))
End Sub

Private Sub showClockFinale()
    Dim pt As Point = Mouse.GetPosition(Nothing)
    Me.uCurClock.Margin = New Thickness(pt.X - 9, pt.Y - 9, 0, 0)
    Me.gridScreen.Visibility = Visibility.Visible
    Me.Cursor = Cursors.None
    Me.UpdateLayout()
End Sub

Private Sub hideClockFinale()
    Me.gridScreen.Visibility = Visibility.Hidden
    Me.Cursor = Cursors.Arrow
    Me.UpdateLayout()
End Sub

Private Sub u_MouseMove(ByVal sender As System.Object, _
    ByVal e As MouseEventArgs) Handles gridScreen.MouseMove

    Dim pt As Point = e.GetPosition(Nothing)
    Me.uCurClock.Margin = New Thickness(pt.X - 9, pt.Y - 9, 0, 0)

    e.Handled = True
End Sub

Private Sub u_MouseEnter(ByVal sender As System.Object, _
    ByVal e As MouseEventArgs) Handles gridScreen.MouseEnter

    Me.uCurClock.Visibility = Visibility.Visible

    e.Handled = True
End Sub

Private Sub u_MouseLeave(ByVal sender As System.Object, _
    ByVal e As MouseEventArgs) Handles gridScreen.MouseLeave

    Me.uCurClock.Visibility = Visibility.Hidden

    e.Handled = True
End Sub

皮莱吉

I need only to show a custom control (a clock with rotating hands) and with this to replace the mouse cursor, the problem is that if I write:

Me.gridScreen.Visibility = Visibility.Visible
' some operations that takes about 1 second
Me.gridScreen.Visibility = Visibility.Hidden
(gridScreen is the grid that contains the user-control)

Obviously I can see nothing, because the update of the UI happens at the end of the procedure. I have tried Me.UpdateLayout(), but it doesn't work.

I have tryed to use the dispacker in many way but none that works :-(

This is my lost attempt:

(uCurClock is the usercontrol, gridScreen a Grid placed at the top-level in the window, with trasparent background, that contains the usercontrol)

Private Sub showClock()
    Dim thread = New System.Threading.Thread(AddressOf showClockIntermediate)
    thread.Start()
End Sub

Private Sub hideClock()
    Dim thread = New System.Threading.Thread(AddressOf hideClockIntermediate)
    thread.Start()
End Sub

Private Sub showClockIntermediate()
    Me.Dispatcher.BeginInvoke(DispatcherPriority.Normal, _
        New Action(AddressOf showClockFinale))
End Sub

Private Sub hideClockIntermediate()
    Me.Dispatcher.BeginInvoke(DispatcherPriority.Normal, _
        New Action(AddressOf hideClockFinale))
End Sub

Private Sub showClockFinale()
    Dim pt As Point = Mouse.GetPosition(Nothing)
    Me.uCurClock.Margin = New Thickness(pt.X - 9, pt.Y - 9, 0, 0)
    Me.gridScreen.Visibility = Visibility.Visible
    Me.Cursor = Cursors.None
    Me.UpdateLayout()
End Sub

Private Sub hideClockFinale()
    Me.gridScreen.Visibility = Visibility.Hidden
    Me.Cursor = Cursors.Arrow
    Me.UpdateLayout()
End Sub

Private Sub u_MouseMove(ByVal sender As System.Object, _
    ByVal e As MouseEventArgs) Handles gridScreen.MouseMove

    Dim pt As Point = e.GetPosition(Nothing)
    Me.uCurClock.Margin = New Thickness(pt.X - 9, pt.Y - 9, 0, 0)

    e.Handled = True
End Sub

Private Sub u_MouseEnter(ByVal sender As System.Object, _
    ByVal e As MouseEventArgs) Handles gridScreen.MouseEnter

    Me.uCurClock.Visibility = Visibility.Visible

    e.Handled = True
End Sub

Private Sub u_MouseLeave(ByVal sender As System.Object, _
    ByVal e As MouseEventArgs) Handles gridScreen.MouseLeave

    Me.uCurClock.Visibility = Visibility.Hidden

    e.Handled = True
End Sub

PIleggi

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦回旧景 2024-10-01 21:47:57

问题与在调度程序上执行的消息的组成无关,而是您在调度程序上执行长时间运行的工作。您必须确保长时间运行/可能阻塞的操作在后台线程上执行。最简单的方法是使用 BackgroundWorker组件。

对不起,C#:

var backgroundWorker = new BackgroundWorker();

backgroundWorker.DoWork += delegate
{
    // long running work goes here
};
backgroundWorker.RunWorkerCompleted += delegate
{
    // change cursor back to normal here
};

// change cursor to busy here

// kick off the background task
backgroundWorker.RunWorkerAsync();

The problem is not to do with the composition of messages being executed on the dispatcher, it's that you're executing long-running work on the dispatcher at all. You must ensure that long-running/potentially blocking operations are executed on a background thread. The easiest way to do so is with the BackgroundWorker component.

Excuse the C#:

var backgroundWorker = new BackgroundWorker();

backgroundWorker.DoWork += delegate
{
    // long running work goes here
};
backgroundWorker.RunWorkerCompleted += delegate
{
    // change cursor back to normal here
};

// change cursor to busy here

// kick off the background task
backgroundWorker.RunWorkerAsync();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文