如果您正在使用 WPF,您确实需要抛弃您可能从古代技术中学到的所有概念,并理解和接受WPF 心态 https://stackoverflow.com/a/15684569/643085.
基本上,你几乎never需要在 WPF 中的过程代码中创建或操作 UI 元素。相反,WPF 适合大量使用数据绑定 http://msdn.microsoft.com/en-us/library/ms752347(v=vs.110).aspx.
WPF 线程模型 http://msdn.microsoft.com/en-us/library/ms741870(v=vs.110).aspx does not允许您在后台线程中创建或操作 UI 元素的实例,并将它们添加到视觉树 http://msdn.microsoft.com/en-us/library/ms753391(v=vs.110).aspx它是由“主”UI 线程创建的。
无论如何,对这样的事情的需求几乎为零,因为在大多数情况下创建 UI 元素是一项可以(并且必须)由 UI 线程执行的微不足道的任务。
而不是担心视觉树,你应该集中精力让你的Data加载到后台线程中,然后作为数据上下文 http://rachel53461.wordpress.com/2012/07/14/what-is-this-datacontext-you-speak-of/到 UI,以便它可以相应地显示您的数据。
这是一个小例子,使用ItemsControl http://drwpf.com/blog/itemscontrol-a-to-z/显示用户列表,该列表在后台线程中异步加载,然后分派到 UI 线程进行显示:
<Window x:Class="WpfApplication7.AsyncItemsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="LightGray" BorderBrush="Black" BorderThickness="1" Margin="2">
<StackPanel>
<TextBlock Text="{Binding LastName}" Margin="2"/>
<TextBlock Text="{Binding FirstName}" Margin="2"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
背后代码:
public partial class AsyncItemsControl : Window
{
public AsyncItemsControl()
{
InitializeComponent();
var dispatcher = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => GetUsers())
.ContinueWith(x => DataContext = x.Result,dispatcher);
}
public List<User> GetUsers()
{
// pretend this method calls a Web Service or Database to retrieve the data, and it takes 5 seconds to get a response:
Thread.Sleep(5000);
return new List<User>
{
new User() {FirstName = "Marty", LastName = "McFly"},
new User() {FirstName = "Emmett", LastName = "Brown"},
new User() {FirstName = "Bufford", LastName = "Tannen"}
};
}
}
数据项:
public class User
{
public string LastName { get; set; }
public string FirstName { get; set; }
}
Result:
请注意,该示例使用 DataBinding,并且它不会在过程代码中创建或操作 UI 元素,而是使用简单的操作User
简单的类string
特性。
另请注意,在 5 秒“加载”时间内,UI 会做出响应,因为实际工作是由后台线程执行的。
这种方法允许 UI 和数据之间更大的分离,从而允许 UI 具有更大的可扩展性和可定制性,而无需更改底层业务/应用程序逻辑。
请注意如何ItemsControl
负责创建和渲染显示 3 个数据项所需的适当 UI 元素。 “每件物品的外观”的实际定义是数据模板 http://msdn.microsoft.com/en-us/library/ms742521(v=vs.110).aspx.
我强烈建议阅读本答案中链接的材料,以便更深入地了解 WPF 的总体工作原理。
旁注:如果您的目标是 C# 5.0,您可以利用async / await
并通过删除所有来使代码更干净Task
为基础的东西。我使用的是 C# 4.0,因此该功能对我来说不可用。
WPF 摇滚。只需将我的代码复制并粘贴到File -> New Project -> WPF Application
并亲自查看结果。
如果您需要进一步的帮助,请告诉我。