TaskFactory New UI Creation

蓝咒 提交于 2019-11-27 02:12:45
Federico Berasategui

If you're working with WPF, you really need to leave behind any and all notions you might have learned from ancient technologies and understand and embrace The WPF Mentality.

Basically, you almost never need to create or manipulate UI elements in procedural code in WPF. Instead, WPF lends itself to heavily use DataBinding.

The WPF Threading Model does not allow you to create or manipulate instances of UI elements in background threads, and add them to the Visual Tree which was created by the "main" UI thread.

Anyways, there is almost zero need for such a thing, because creating UI elements is in most cases a trivial task which can (and must) be performed by the UI Thread.

rather than worrying about the Visual Tree, you should concentrate on having your Data loaded in background threads, and then passed as a DataContext to the UI so that it can display your data accordingly.

This is a small example which uses an ItemsControl to display a list of users, which are loaded asynchronously in a background thread and then dispatched to the UI thread for display:

<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>

Code Behind:

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"}
        };
    }
}

Data Item:

public class User
{
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

Result:

  • Notice that the example uses DataBinding and it does not create or manipulate UI elements in procedural code, but rather operates with a simple User class with simple string properties.

  • Also notice that during the 5 seconds "load" time, the UI is responsive because the actual work is being performed by a background thread.

  • This approach allows a greater separation between UI and data which allows a much greater scalability and customizability of the UI without having to change the underlying business / application logic.

  • Notice how the ItemsControl takes care of creating and rendering the appropiate UI elements needed to display the 3 Data Items. The actual definition of "how each item looks" is the DataTemplate.

  • I strongly recommend reading the material linked thoughout this answer for more in-depth understanding of how WPF works in general.

  • Side note: if you're targetting C# 5.0 you can leverage async / await and make this code cleaner by removing all the Task based stuff. I'm on C# 4.0 so that feature is not available for me.

  • WPF Rocks. Just copy and paste my code in a File -> New Project -> WPF Application and see the results for yourself.

  • Let me know if you need further help.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!