wpf принудительно обновляет окно интерфейса во время процедуры - PullRequest
0 голосов
/ 23 сентября 2010

Мне нужно только показать пользовательский элемент управления (часы с вращающимися стрелками) и этим заменить курсор мыши, если я использую файл .cur или .ani для замены курсора мыши Me.CUrsor = New Cursor («абсолютный путь к файлу .ani») нет проблем: я могу изменить курсор во время процедуры: но качество анимации очень плохое, а также, по другим причинам, я бы предпочел использовать мой маленький пользовательский элемент управления. Проблема в том, что если я напишу:

Me.gridScreen.Visibility = Visibility.Visible

'некоторые операции, которые занимают около 1 секунды

Me.gridScreen.Visibility = Visibility.Hidden

(gridScreen - это сетка, содержащая пользовательский элемент управления)

Очевидно, я ничего не вижу, потому что обновление пользовательского интерфейса происходит в конце процедуры. Я пробовал Me.UpdateLayout (), но он не работает.

Я пытался использовать диспетчер разными способами, но ни один из них не работает: - (

Это моя потерянная попытка:

(uCurClock - это пользовательский контроль, gridScreen a Grid, расположенный на верхнем уровне в окне, с прозрачным фоном, который содержит пользовательский контроль)

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

Ответы [ 2 ]

1 голос
/ 06 сентября 2011

ссылка Описание класса DispatcherFrame

хорошая оле DoEvents для WPF !!!

Public Sub DoEvents()
    Dim frame As New DispatcherFrame()
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, New DispatcherOperationCallback(AddressOf ExitFrame), frame)
    Dispatcher.PushFrame(frame)
End Sub

Public Function ExitFrame(ByVal f As Object) As Object
    CType(f, DispatcherFrame).Continue = False
    Return Nothing
End Function
1 голос
/ 05 ноября 2010

Хотя следующий код будет делать то, что вы просите, я подозреваю, что на самом деле это вам не поможет, так как вы упомянули анимацию. Вам нужно будет использовать несколько потоков. Однако, просто чтобы продемонстрировать, почему это так, вот что отвечает на вопрос, который вы задали:

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, это сделает его видимым во время выполнения медленной процедуры.

Но анимации не запускаются. Проблема в том, что если вы делаете что-то медленное в потоке пользовательского интерфейса, поток пользовательского интерфейса не может делать ничего другого - он не может запускать анимации, он не может реагировать на пользовательский ввод. В основном пользовательский интерфейс заморожен. Единственная причина, по которой код, показанный здесь, даже делает пользовательский элемент управления видимым, заключается в том, что он в основном говорит: «Выполните любую выдающуюся работу потока пользовательского интерфейса сейчас», что имеет побочный эффект обработки вашего изменения свойства Visible.

Но анимации тоже происходят в потоке пользовательского интерфейса.

Если вы хотите сделать это правильно, вам нужно выполнить работу в фоновом потоке, возможно, с помощью BackgroundWorker или написав свой собственный код многопоточности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...