我制作了一个自定义控件,由一些网格、堆栈面板和文本块组成。我想将其用作 ListBox 项。我正在使用它在列表的每个项目中显示多行信息,就像它在图像中显示的那样。该控件的名称是 ItemDetail。
为了填写列表,我单击上面的每个按钮,这些按钮会进行 SQL 查询(查询有时可能需要大约 5 秒,并且用户界面已冻结,这一点非常明显)。
为了解决这个问题,我使用 BackgroundWorker 进行 SQL 查询,并在每次返回查询的结果行时报告进度。
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();
}
我正在使用 BackgroundWorker 的 IsProgressChanged 事件将数据添加到 ItemDetail 的实例,然后将其添加到 ListBox。
void _worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ItemDetail item = new ItemDetail((DataRow)e.UserState);
Elementos_Lista.Items.Add(item);
}
这样,操作花费的时间少了很多,但它仍然冻结,这是由于在返回查询的每一行后必须进行 UI 刷新。BackgroundWorker 不允许我在单独的线程中将数据添加到 ItemDetail 控件,因为它不是 UI 线程。
有没有一种方法可以加快一次渲染大量控件的过程,或者将它们以较小的批次添加到列表中,这样 UI 在完成填充列表之前似乎不会完全没有响应?