Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Busy" Effect Overlay

Tags:

wpf

I have a wpf application which does very heavy actions in which the user needs to wait while the application "thinks".

What I want to do is, while the main thread of the application is thinking, another thread will disable the whole window and give it kind of a grayish color and a circular progress bar will appear in the middle of the screen.

It's kind of a big question and I don't really need the whole code to do this just the general Idea.

Thanks for all your help..

like image 513
Matt Starr Avatar asked Jan 03 '12 10:01

Matt Starr


3 Answers

In addition to the above suggestions (Background worker, Dispatcher) - yes these are the correct techniques to get what you want, but let me discuss the UI effect you requested in your question. If you are using the MVVM pattern, you can create some "I'm busy" UI and bind to an IsBusy property in the view model to show and hide the UI. For instance:

public class MyViewModel : INotifyPropertyChanged
{
    // Bind to this property any UI you want to 
    // show/hide during long running updates
    public bool IsBusy 
    { 
        get { return _isBusy; } 
        set 
        {
            _isBusy = true; 
            OnPropertyChanged("IsBusy");
        }
    } 

    private void OnPropertyChanged(string prop)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(prop));
        }
    }

    // Note: This is intended to be called on a background thread
    private void DoLongRunningOperationOnABackgroundThread()
    {
        try
        {
            IsBusy = true;

            // do your work
        }
        finally
        {
            IsBusy = false;
        }
    }
}

Then in the UI use this xaml (or similar)

<UserControl:MyControl x:Class="MyApp.MyControl"
                          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <UserControl.Resources>
        <BooleanToVisibilityConverter x:Key="boolToVis"/>
    </UserControl.Resources>
    <Grid>
        <!-- your UI code goes here -->

        <!-- Below this, at higher Z-Order place a control to gray out the screen when IsBusy = true -->
        <Border Background="#55000000" BorderThickness="0" Visibility="{Binding IsBusy, Converter={StaticResource boolToVis}}">
            <TextBlock Text="I AM BUSY!" Font-Size="32" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White"/>
        </Border>
    <Grid>
</UserControl>    

The net effect will be when you use a background worker or threadpool to call the DoLongRunningOperation function in your viewmodel, the border defined in Xaml will show/hide as the operation starts/stops. You won't need the dispatcher to invoke here either as WPF handles the thread marshalling for you.

There are implementations of busy controls with whirlygig animations etc... on the net too to spice up the UI.

Best regards,

like image 157
Dr. Andrew Burnett-Thompson Avatar answered Nov 04 '22 09:11

Dr. Andrew Burnett-Thompson


Use Dispatcher.BeginInvoke to change the Enable-Property of the UI components and show/hide the progressbar out of the worker thread

for the worker-thread you can use the BackgroundWorker-Class

like image 4
0xDEADBEEF Avatar answered Nov 04 '22 09:11

0xDEADBEEF


Offload the heavy action to a new thread and do the UI stuff (disable, gray out and progress bar) on the main thread. See BackgroundWorker and Dispatcher.

Using a new thread for the UI stuff is possible, but not using the existing Window. A UI control (Dispatcher) can online be used/called by the thread it belongs to. You could however create a new thread and use a new Window with a new Dispatcher to do the UI stuff. You would then have to position the new Window over the original. Not as easy as my first suggestion. It might be an option if you don't know when the heavy action is executed. See here, here and here.

like image 2
Lars Truijens Avatar answered Nov 04 '22 10:11

Lars Truijens