【问题标题】:Wpf list async updateWpf 列表异步更新
【发布时间】:2015-07-25 03:07:56
【问题描述】:

我有加载一些长加载日期的列表。我不能使用 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>

【问题讨论】:

  • This answer 可能会有所帮助。
  • 进行长时间的操作,然后在 UI 线程上更新 UI。 UI 无法观察列表,因此没有任何效果。调用 RaisePropertyChange("Items") 将无济于事,因为 ListView 将看到对象实际上并未更改并忽略它。

标签: c# wpf


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    一些事情:

    您不需要在 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}));
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-13
      • 2013-06-08
      • 1970-01-01
      • 1970-01-01
      • 2021-08-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多