Jesús Otero
Jesús Otero

Reputation: 309

Adding WPF Custom Controls in batch to a ListBox without freezing the UI

I made a custom control, consisting of a few grids, stackpanels and textblocks. Which i want to use as a ListBox Item. I am using it to display more than one line of information in each item of the list, like it's shown in the image. The control's name is ItemDetail.

Custom control for listbox

To fill the list, i click on each of the buttons above, which make a SQL query (the query can sometimes take about 5 seconds, and makes it more than noticeable that the UI has frozen).

To fix that, I'm using a BackgroundWorker for the SQL query, and reporting the progress everytime a resulting row from the query is returned.

private void Departamento_Click(object sender, MouseButtonEventArgs e)
    {
        Elementos_Lista.Items.Clear();
        BackgroundWorker _worker = new BackgroundWorker();
        _worker.WorkerReportsProgress = true;
        _worker.ProgressChanged += new ProgressChangedEventHandler(_worker_ProgressChanged);

        _worker.DoWork += delegate(object s, DoWorkEventArgs args)
        {
           //SQL query
           reglas.Consulta("cerrado='0' and grupo='3' order by fecha desc");   

            foreach (DataRow dr in reglas.Entidad.tabla.Rows)
            {
                _worker.ReportProgress(0, dr);
            }

        };
        _worker.RunWorkerAsync();
    }

And I'm using the BackgroundWorker's IsProgressChanged event to add the data to an instance of ItemDetail, and then adding it to the ListBox.

 void _worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        ItemDetail item = new ItemDetail((DataRow)e.UserState);
        Elementos_Lista.Items.Add(item);
    }

This way, the operation takes a lot less time, but it still freezes, and it's due to the UI refresh that has to be done after each row of the query is returned. The BackgroundWorker doesn't let me add the data to the ItemDetail control in a separate thread, because it's no the UI thread.

Is there a way I can speed up the process of rendering a lot of controls at once or add them in smaller batches to the list, so the UI doesn't seem completely unresponsive until it's done filling the list?.

Upvotes: 0

Views: 588

Answers (1)

brunnerh
brunnerh

Reputation: 184441

Just add the data to an ObservableCollection which should be bound to your list control and let it generate the controls via data templates, if you have virtualization unnecessary controls (the ones scrolled out of view) will not be created right away which should make the operation faster.

Upvotes: 2

Related Questions