Arno Greiler
Arno Greiler

Reputation: 53

disabling a window

In my application I have a Button. If the button is clicked as select against a database is executed and the result is shown in a ListView. As the select is quite complex, it takes some time to retrieve the data.

When I click the Button, the Application-Window should be disabled until the data is loaded. But when I set the IsEnabled-Property of the Window to false, the window gets disabled after the data is loaded.

I tried to disable the Window in an other thread with a BackgroundWorker. But then I get an exception that the window is already in use by another thread.

How can I disable the Window bevore it retrieves the data?

Upvotes: 1

Views: 141

Answers (4)

Akash Kava
Akash Kava

Reputation: 39916

I will suggest "BusyDialog" window in addition to background thread.

Yous busy dialog can be an animation displaying it is doing something, and modally blocking any user input as well.

public partial class BusyDialog : Window
{
    public BusyDialog()
    {
        InitializeComponent();
    }

    public static T Execute<T>(DependencyObject parent, Func<T> action)
    {

        Window parentWindow = null;
        if (parent is Window)
        {
            parentWindow = parent as Window;
        }
        else
        {
            parentWindow = Window.GetWindow(parent);
        }

        T val = default(T);
        Exception le = null;
        BusyDialog bd = new BusyDialog();
        bd.Owner = parentWindow;
        ThreadPool.QueueUserWorkItem((o) =>
        {
            try
            {
                val = action();
            }
            catch (Exception ex)
            {
                le = ex;
            }
            bd.EndDialog();
        });
        bd.ShowDialog();
        if (le != null)
        {
            Trace.WriteLine(le.ToString());
            throw new Exception("Execute Exception", le);
        }
        return val;
    }

    private void EndDialog()
    {
        Dispatcher.Invoke((Action)delegate() {
            this.DialogResult = true;
        });
    }

}

Now you can use following way to call your method asynchronously,

List<Result> results = BusyDialog.Execute( this , 
   ()=>{
       return MyLongDatabaseLoadingCall();
   });

This is what happens,

  1. BusyDialog is displayed modally, blocking any user input as well as displaying busy animation
  2. A call to your method MyLongDatabaseLoadingCall is executed in ThreadPool.QueueUserItem, which asynchronously calls your method in different thread (Same as background threading functionality suggested by others here).
  3. Animation continues till the call is executing
  4. When your method ends, BusyDialog is ended and everything is back to how it was.

Upvotes: 0

Johnny
Johnny

Reputation: 1575

try this:

BackgroundWorkerHelper.DoWork<Type of object you want to retrieve>(
                   () =>
                   {
                      //Load your data here
                      //Like
                        using (MarketingService svc = new MarketingService())
                        {
                            return svc.GetEmployeeLookupTable();
                        }
                   },
                       (args) =>
                       {
                           this.IsEnable = true;
                           if (args.Error == null)
                           {
                               Your Target Datasource= args.Result;
                           }
                       });

this.IsEnable = false;

Upvotes: 0

Adam Sills
Adam Sills

Reputation: 17062

You did the wrong thing in a background thread. You have to affect the UI from the UI thread, and your data loading should occur in a background thread.

The simplest approach is to use a BackgroundWorker to load your data, store that data in a class-level variable, and when your background work is complete, the UI re-enables and loads the data from the class-level variable.

Upvotes: 2

Lazarus
Lazarus

Reputation: 43084

I'd think you'd move the database activity to the background thread to leave your UI responsive (even if it's only to disable it) rather than the other way around.

Upvotes: 1

Related Questions