R. Wood
R. Wood

Reputation: 101

WPF Application Freezing when getting Data and refreshing DataGrids

I have a set of functions populating different DataGrids with EF objects similar to this:

var items = db.Items.AsNoTracking().Where(n => n.CategoryId == categoryId);
var grid = grdItems as DataGrid;
grid.ItemsSource = items;

The problem I have is that the window freezes i.e. cannot click or do anything until the above code is finished. Once finished, the grids are populated correctly so no issues there, but for the brief few seconds it appears to have crashed.

I wanted to add a simple loading type window/dialog so at least the UI displays something for the user than seeming like it has crashed. My problem is that adding a frm.Show, frm.Hide before/after this code above or trying to use a UserControl overlay, it never actually displays it because I expect the thread is busy.

I haven't been using WPF for very long and historically I used Forms where in cases like this I would use DoEvents but its my understanding this is likely to be more harmful than useful so I'm asking for the best possible way to update the UI with a loading overlay please. Particularly in the case of a DataGrid being populated and I expect any Converters/Vaildators being processed are contributing to the thread being busy.

Upvotes: 1

Views: 895

Answers (2)

mm8
mm8

Reputation: 169320

You should either fetch the items asynchronously:

progressBar.Visibility = Visibility.Visible;
var items = await db.Items.AsNoTracking().Where(n => n.CategoryId == categoryId)
    .ToListAsync();
progressBar.Visibility = Visibility.Collapsed;

...or do it synchronously on a background thread:

var items = await Task.Run(() => db.Items.AsNoTracking()
    .Where(n => n.CategoryId == categoryId)
    .ToList());

See Asynchronous programming with async and await for more information about asynchronous programming in C#.

Upvotes: 2

ChrisBD
ChrisBD

Reputation: 9209

Data access should really be performed using asynchronous calls away from the UI.

Typically this is done using a Command implementation (called from the UI) which in turn triggers off an async Task.

This Task can be used to set a Boolean flag to show that the system is busy, which in turn can be bound to indicate this to the user.

Upvotes: 0

Related Questions