Wpf列表异步更新

时间:2015-07-24 15:14:40

标签: c# wpf

我有加载一些长装载日期的清单。我不能使用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代码gere

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

2 个答案:

答案 0 :(得分:1)

只要在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);
    }
}

答案 1 :(得分:0)

一些事情:

您的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}));
        }
    }
}