Reputation: 53
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
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,
Upvotes: 0
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
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
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