我提升了两个用户控件。
第一个包含一个ItemsControl
,我必须用我的第二个用户控件动态填充它。第二个用户控件可以递归地包含另一个ÌtemsControl
,因此它是一个非常重要的控件来初始化。
以下是我为SubControl
所做的事情:
public sealed partial class SubControl : UserControl
{
public SubControl(ModelA item)
{
this.InitializeComponent();
this.DataContext = item;
//if the current item has child items, add them to the ItemsControl:
if(item.SubItems != null)
{
BuildUI(item.SubItems);
}
}
private void BuildUI(List<AbstractModel> data)
{
foreach(var item in data)
{
var dataItem = item as ModelA;
//we only want item of type ModelA in our ItemsControl:
if(dataItem != null)
{
SubElements.Items.Add(new SubControl(dataItem));
}
}
}
}
现在,我首先为MainControl
ItemsControl
(名为Elements
)将包含一组SubControl
的内容撰写的内容:
public sealed partial class MainControl : UserControl
{
public MainControl(List<AbstractModel> data)
{
this.InitializeComponent();
BuildUI(data);
}
private void BuildUI(List<AbstractModel> data)
{
foreach(var item in data)
{
var dataItem = item as ModelA;
if(dataItem != null)
{
Elements.Items.Add(item);
}
}
}
}
我注意到在构建这个“树”时UI的小冻结,但我目前正在使用功能非常强大的计算机。我希望应用程序即使在较小的设备(如Windows Surface RT)上也能顺利运行。所以我更改了MainControl
代码:
public sealed partial class MainControl : UserControl
{
public MainControl(List<AbstractModel> data)
{
this.InitializeComponent();
BuildUI(data);
}
private async void BuildUI(List<AbstractModel> data)
{
var list = new List<SubControl>();
await Task.Run(() =>
{
foreach(var item in data)
{
var dataItem = item as ModelA;
if(dataItem != null)
{
list.Add(new SubControl(dataItem));
}
}
});
foreach(var item in list)
{
Elements.Items.Add(item);
}
}
}
我们的想法是在不同的线程中构建所有SubControl
,以便不阻止UI,并且当所有用户控件都已初始化时,我们会将它们添加到ItemsControl
中MainControl
。 1}}。
然而,由于数据的编组,这不起作用,即使UI上实际上没有单个SubControl
!它在构建SubControl
时崩溃,这真的很奇怪,因为它对实际UI没有任何影响;它们只是添加到临时List
。
在后台任务中构建这些用户控件可能有什么技巧,因此UI不会冻结?
答案 0 :(得分:4)
Windows UI非常单线程。必须创建每个UI控件,并且仅在单个线程中使用。没有办法解决这个问题。
所以,现在是时候考虑解决方案了。创建几十个控件没有问题;用户界面处理就好了。您正在谈论将数百或数千个项目添加到列表控件,这只是一个无法使用的UI。因此,正确的解决方案是重新考虑您的UI设计。也许你可以把结果分成几类或类别。
如果您已经考虑过您的UI设计并且仍然确定要向用户显示数百或数千个项目,那么答案就是使用virtualization。这比简单的foreach
循环更难编码,但它是有效显示大量数据的唯一方法。
答案 1 :(得分:-1)
有很多方法可以做到这一点。
您可以使用此工作流程:
[...]因为它对实际用户界面没有任何影响;它们只是添加到临时列表
顺便说一句:您的代码确实崩溃了,因为您在异步方法中添加了控件,这实际上是一个非GUI线程。所以你的命题错了。