繁体   English   中英

WPF列表异步更新

[英]Wpf list async update

我有加载时间较长的列表。 我不能使用ObservableCollection,因为它不能从另一个线程更新。 我需要做的是,因为当我使用列表时,UI上没有任何反应

public class ListViewModel : ViewModelBase
{
    /// <summary>
    /// Initializes a new instance of the ListViewModel class.
    /// </summary>
    /// 
    private List<StructOfList> items;

    public List<StructOfList> Items 
    {
        get { return items; }
        set
        {
            items = value; 
            RaisePropertyChanged("Items");
        }
    }

    public ListViewModel()
    {
        Items = new List<StructOfList>();
        Items.Add(new StructOfList { Amount = 10, FirstName = "Test", SecondName = "Test" });
        AsyncDataLoad();
    }

    public void AsyncDataLoad()
    {
        Action<List<StructOfList>> LoadData = new Action<List<StructOfList>>(AddItemToList);
        IAsyncResult result = LoadData.BeginInvoke(Items, null, null);
    }

    public void AddItemToList(List<StructOfList> items)
    {
        for (int i = 0; i < 10; i++)
        {
            System.Threading.Thread.Sleep(300);
            items.Add(new StructOfList {FirstName = "First" , SecondName = "Second" , Amount = i});
            RaisePropertyChanged("Items");
        }
    }
}

XAML代码大失所望

<Grid>
    <ListView ItemsSource="{Binding Items}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Label Content="{Binding FirstName}" Grid.Column="0"></Label>
                    <Label Content="{Binding SecondName}" Grid.Column="1"></Label>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

只要更新发生在UI线程上,就可以使用ObservableCollection 由于您所拥有的只是一个async函数,它仅执行无冲突的事务(例如顺序添加),因此使用DispatcherObservableCollection发生更改时应用更改应该没有问题:

public void AddItemToList()
{
    for (int i = 0; i < 10; i++)
    {
        System.Threading.Thread.Sleep(300);

        var AddItem = new Action(() => items.Add(new StructOfList { FirstName = "First", SecondName = "Second", Amount = i });
        Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, AddItem);
    }
}

一些东西:

您不需要在Items属性上具有RaisePropertyChanged ,因为Items对象仅更新一次(在CTOR中)。

您应该使用async / await来执行异步数据加载。

您还应该使用OverservableCollection因为您的列表将更新项目。

例如:

public class ListViewModel : ViewModelBase
{
    public ObservableCollection<StructOfList> Items 
    {
        get; private set;
    }

    public ListViewModel()
    {
        Items = new ObservableCollection<StructOfList>();
        Items.Add(new StructOfList { Amount = 10, FirstName = "Test", SecondName = "Test" });
        AsyncDataLoad();
    }

    public void async AsyncDataLoad()
    {
        await Task.Run(()=> AddItemsToList());
    }

    public void AddItemsToList()
    {
        for (int i = 0; i < 10; i++)
        {
            Application.Current.Dispatcher.Invoke(() => Items.Add(new StructOfList {FirstName = "First" , SecondName = "Second" , Amount = i}));
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM