Search code examples
c#xamluwptreeviewuwp-xaml

UWP TreeView loading leafs of element on treeView_Expanding does block the tree


Team, I have a data structure a little complex, here a more detailed description. When I click to expand the items even if I used await/async the UI does not show me the expanding elements but remains on hold till all the leafs are created. On very big sub structures I would have expected to have it opened and see the items to be added incrementally.

I'm doubtfull of which is the more appropriate behaviour: 1) having the leafs shown while building opens up to issues if the uses clicks around while the tree is still being built. So I'm not sure I like this 2) as the process could take some time I'd like to show something like "loading" or an appropriate visual feedback for what's going on. But do not know how to do.

What would you recomend?

More information: The project has a patients and visits under each patient. The structure is completely dynamic so the number of levels under a patient cannot be known in advance as each visit can have sub visits and documents associated to the visit.

The number of patients could be extremly high (10K+). The first performance issue I got was that loading everything patients and all the visits in one shot would require too much time (> 1 min!) so, following several guidances, I've adopted an approach where only the patients are loaded and an empty leaf is created IF a patient has visits. When a patient is expanded all the leafs for the patient are loaded. The depth and structure completely changes from patient to patient. So there are some that very quick to load (1 level or few visits in total) and some that require up to 1 or more seconds as they can have 50+ visits on 5 or more levels.

As I'm using SQLServer Express I've checked and there is NO relevant impact from the queries to retrieve data from the DB as they are around milliseconds.

Connection with the DB is done via EFCore and the leaf items are loaded via LINQ with awaitable ToListAsync in recoursive more: Patient will load the leafs connected to him. When the leaf is loaded will look and load sub leafs... sub leafs will behave in the same way.

So I would have NOT expected any delays in the UI.

Here the code to load leafs on Patients that do have a visit and is NOT already loaded

private async void treeView_Expanding(WinUI.TreeView sender, WinUI.TreeViewExpandingEventArgs args)
{
    if (args.Item is MTreeViewPaz)
    {
        if ((((MTreeViewPaz)args.Item).VisitsN > 0) && (((MTreeViewPaz)args.Item).Loaded == LoadingStatus.NotStarted))
        {

            await ((MTreeViewPaz)args.Item).LoadDataAsync();
        }
    }
}

In the leafs exactly the same logic applies:

public async Task LoadDataAsync()
{
    Loaded = LoadingStatus.Loading;

    var aList = App.gDataContext.Cache.VVisitHierarchy
        .Where(a => a.CodPaz == _PazV.CodPaz && a.Parent == null)
        .OrderBy(b => b.CreationOrd).ThenBy(b => b.Data).ThenBy(b => b.CodPar)
        .ToList();
    foreach (var item in aList)
    {
        if (item.Visits > 0)
        {
            MTreeViewVisit aMVisit = new MTreeViewVisit(item);

            Visits.Add(aMVisit);
            if (item.Visits > 0)
            {
                await aMVisit.LoadDataAsync();
            }
        }
    }
    Visits.RemoveAt(0);
    Loaded = LoadingStatus.Loaded;
}

Solution

  • I found this:

        var aList = await Task.Run(() => App.gDataContext.Cache.VVisitHierarchy
            .Where(a => a.CodPaz == _PazV.CodPaz && a.Parent == null)
            .OrderBy(b => b.CreationOrd).ThenBy(b => b.Data).ThenBy(b => b.CodPar)
            .ToList());
    

    that unlocks the UI and allows the leafs to be shown while created. But is it good?