wpf在过程中强制更新UI窗口 [英] wpf forcing update UI window during a procedure

查看:980
本文介绍了wpf在过程中强制更新UI窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我使用文件.cur或.ani替换鼠标光标,我只需要显示一个自定义控件(带有旋转指针的时钟)并以此替换鼠标光标. Me.CUrsor =新光标(".ani文件的绝对路径") 没问题:我可以在过程中更改光标:但是动画的质量很差,并且由于其他原因,我更喜欢使用我的小用户控件.问题是,如果我写:

I need only to show a custom control (a clock with rotating hands) and with this to replace the mouse cursor, if I use a file .cur or .ani to replace the mouse cursor Me.CUrsor = New Cursor("absolute path of the .ani file") there is no problem: I can change the cursor during a procedure: but the quality of the animation is very bad, and, also for other reasons, I'd prefer to use my little user-control. The problem is that if I write:

Me.gridScreen.Visibility = Visibility.Visible

Me.gridScreen.Visibility = Visibility.Visible

'大约需要1秒钟的操作

' some operations that takes about 1 second

Me.gridScreen.Visibility = Visibility.Hidden

Me.gridScreen.Visibility = Visibility.Hidden

(gridScreen是包含用户控件的网格)

(gridScreen is the grid that contains the user-control)

很明显,我什么也看不到,因为UI的更新发生在过程的结尾.我已经尝试过Me.UpdateLayout(),但是它不起作用.

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 :-(

这是我失败的尝试:

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

(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()G
    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

推荐答案

尽管以下代码可以满足您的要求,但由于您提到了动画,我怀疑它实际上对您没有帮助.您将需要使用多个线程.但是,仅为了说明原因,以下是可以回答您所问问题的信息:

While the following code will do what you ask for, I suspect it won't actually help you, since you've mentioned animation. You're going to need to use multiple threads. However, just to demonstrate why that is, here's something that answers the question you've asked:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click

    uc1.Visibility = Visibility.Visible
    Cursor = Cursors.Wait

    ' Push visibility changes now.
    ' (Sort of like DoEvents - and a horrible idea for exactly the same
    ' reasons that DoEvents was a total train wreck. Never actually do
    ' this - use a background thread instead.)
    Dim df As New DispatcherFrame(True)
    Dispatcher.BeginInvoke(Sub() df.Continue = False, DispatcherPriority.ContextIdle)
    Dispatcher.PushFrame(df)

    Thread.Sleep(1000)

    ClearValue(CursorProperty)
    uc1.Visibility = Visibility.Hidden

End Sub

假设您在页面上有一个名为uc1的用户控件,这将在运行缓慢的过程时将其强制显示.

Assuming you have some usercontrol called uc1 on the page, this will force it to be visible while your slow procedure runs.

但是不会播放动画.问题是,如果您在UI线程上执行缓慢的操作,则UI线程无法执行其他任何操作-它无法运行动画,也无法响应用户输入.基本上,UI是冻结的.此处显示的代码甚至使用户控件可见的唯一原因是,它基本上说立即执行任何出色的UI线程",这具有处理对Visible属性所做的更改的副作用.

But no animations will run. The problem is, if you're doing something slow on the UI thread, the UI thread can't do anything else - it can't run animations, it can't respond to user input. Basically the UI is frozen out. The only reason the code shown here even makes the user control visible is that it basically says "do any outstanding UI thread work now", which has the side effect of processing your change to the Visible property.

但是动画也会在UI线程上发生.

But animations happen on the UI thread too.

如果要正确执行此操作,则需要在后台线程上进行工作,可能需要使用BackgroundWorker或编写自己的线程代码.

If you want to do this properly, you need to do the work on a background thread, possibly by using the BackgroundWorker, or by writing your own threading code.

这篇关于wpf在过程中强制更新UI窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆