views:

451

answers:

1

I want to set the Text of a TextBlock in my StatusBar before making the user wait for a short moment while my program does a little bit of work.

Aparently, instead of doing a nice little function like this (which does not work):

Function Load(ByVal Id As Guid) As Thing
    Cursor = Cursors.Wait
    TextBlockStatus.Text = "Loading..."
    TextBlockStatus.UpdateLayout()
    Dim Found = From t In db.Thing _
                Where t.Id = Id _
                Select t
    TextBlockStatus.Text = String.Empty
    Cursor = Cursors.Arrow
    Return Found
End Function

I have to instead use this monstrosity:

Private WithEvents LoadWorker As BackgroundWorker

Private Sub Window1_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
    InitializeLoadWorker()
End Sub

Private Sub InitializeLoadWorker()
    LoadWorker = New BackgroundWorker
    LoadWorker.WorkerSupportsCancellation = False
    LoadWorker.WorkerReportsProgress = False
    AddHandler LoadWorker.DoWork, AddressOf LoadBackgroundWorker_DoWork
    AddHandler LoadWorker.RunWorkerCompleted, AddressOf LoadBackgroundWorker_RunWorkerCompleted
End Sub

Sub Load(ByVal Id As Guid)
    Cursor = Cursors.Wait
    LoadWorker.RunWorkerAsync(Argument)
End Sub

Private Sub LoadBackgroundWorker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
    Dim Worker As BackgroundWorker = DirectCast(sender, BackgroundWorker)
    Dim Id As Guid = DirectCast(e.Argument, Guid)
    e.Result = From t In db.Thing _
               Where t.Id = Id _
               Select t
End Sub

Private Sub LoadBackgroundWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
    TextBlockStatus.Text = String.Empty
    Cursor = Cursors.Arrow
    Dim Found As Thing = DirectCast(e.Result, Thing)
    'now do something with the found thing here instead of where Load() is called.'
End Sub

And the Load() Function is now a Sub!!

There must be a better way to handle such a simple situation. This doesn't need to be asynchronous.

+1  A: 

Have a look at this question: Display Wait Screen in WPF.

The accepted answer has a way of doing what I think you want, without a Background worker class.

From the link in the answer to the other question, this might work for VB.NET (I haven't tried it though)

Public Sub AllowUIToUpdate()

    Dim frame As New DispatcherFrame()

    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, New DispatcherOperationCallback(AddressOf JunkMethod), frame)

    Dispatcher.PushFrame(frame)

End Sub

Private Function JunkMethod(ByVal arg As Object) As Object

    DirectCast(arg, DispatcherFrame).Continue = False
    Return Nothing

End Function
Ray
Updatd with VB.NET code.
Ray
Beautiful. Thank you!
Zack Peterson