首页 > 解决方案 > 在构造函数中运行异步方法会停止 ObservableCollection 显示数据

问题描述

在构造函数中调用异步方法时出现问题。ObservableCollection即使我在跟踪代码时可以在调试中看到它,它也会停止显示数据。为了解决这个问题,我有一个相同方法的非异步版本,但显然这并不理想。如何让我的异步方法在构造函数中正常工作?

如果我调用this.RefreshCarList("")构造函数,MainWindowViewModel那么后续调用this.RefreshCarListAsync("")(不是从构造函数内部)将工作得非常好,并且数据会显示在屏幕上。如果我只打电话this.RefreshCarListAsync(""),那么数据永远不会显示。

public class MainWindowViewModel
{
    private ObservableCollection<Car> carList;
    public ICollectionView CarList { get; private set; }
    private DataReceivedHandler dataReceivedHandler = new DataReceivedHandler();

    public MainWindowViewModel()
    {
        //this.RefreshCarList(""); // Gets data on startup
        this.RefreshCarListAsync("") // Doesn't show any data
        this.CarList = new QueryableCollectionView(this.carList, typeof(Car));
    }

    public void RefreshCarList(string carBrand)
    {
        this.carList = this.dataReceivedHandler.GetCarList(carBrand);
    }

    public async Task RefreshCarListAsync(string carBrand)
    {
        this.carList = await this.dataReceivedHandler.GetCarListAsync(carBrand);
    }
}

视图模型使用从服务获取数据的数据接收器类:

public class DataReceivedHandler
{
    private CarDataService dataService = new CarDataService();
    private List<Car> carList = new List<Car>();
    private ObservableCollection<Car> carOC = new ObservableCollection<Car>();


    public ObservableCollection<Car> GetCarList(string carBrand)
    {
        carListFromService = this.dataService.GetCarList(carBrand);
        this.carOC.Clear();
        foreach (ICar car in carListFromService)
            this.carOC.Add(car);
        

        return (this.carOC);
    }

    public async Task<ObservableCollection<Car>> GetCarListAsync(string carBrand)
    {
        carListFromService = await Task.Run(() => this.dataService.GetCarList(carBrand)).ConfigureAwait(false);
        this.carOC.Clear();
        foreach (ICar car in carListFromService)
            this.carOC.Add(car);

        return (this.carOC);
    }
}

服务:

public class CarDataService
{
    private List<Car> CarList = new CarList();
    public List<Car> GetCarList(string carBrand)
    {
        return this.CarList;
    }
}

更新:

所以我已经尝试了这个作为建议的答案之一,但是它仍然不起作用:

public async Task Initialise()
{
    try
    {
        await this.CarListAsync("");
        this.CarList = new QueryableCollectionView(this.carList, typeof(Car));
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

this.viewModel.Initialise(); // in a different class

标签: c#wpfasync-awaittask

解决方案


如果在构造函数返回后动态设置属性,则应在类中实现INotifyPropertyChanged并引发PropertyChanged事件MainWindowViewModel

public class MainWindowViewModel : INotifyPropertyChanged
{
    private ICollectionView  carList;
    public ICollectionView  CarList
    {
        get { return carList; }
        private set { carList = value; NotifyPropertyChanged(); }
    }

    private DataReceivedHandler dataReceivedHandler = new DataReceivedHandler();

    public async Task Initialise()
    {
        try
        {
            await this.CarListAsync("");
            this.CarList = new QueryableCollectionView(this.carList, typeof(Car));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    // This method is called by the Set accessor of each property.  
    // The CallerMemberName attribute that is applied to the optional propertyName  
    // parameter causes the property name of the caller to be substituted as an argument.  
    private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

推荐阅读