C# WPFでObservableCollectionを非同期で更新する方法

WPFで非同期更新可能なObservableCollectionを実装。AsyncObservableCollectionとPageMstCollectionの例を紹介

技術公開日 読了目安 1 分

WPFアプリケーションでは、UIスレッドとバックグラウンドスレッドの間でデータを同期する必要があります。
そのため、非同期でデータを取得し、UIに反映するためのObservableCollectionを実装します。
この記事では、その方法について説明します。

ObservableCollectionの非同期更新

WPFでは、UIへの変更はUIスレッドで行わなければなりません。しかし、非同期処理を行いつつUIを更新する必要がある場合、BindingOperations.EnableCollectionSynchronizationとlock文を使うことで簡単に実現できます。

public class PageMstCollection : ObservableCollection<PageMstViewModelEntity>
{
    private readonly object _lock = new object();
    private readonly IPageMstRepository _pageMstRepository;

    public PageMstCollection(IPageMstRepository pageMstRepository)
    {
        _pageMstRepository = pageMstRepository;
        BindingOperations.EnableCollectionSynchronization(this, _lock);
    }

    public async Task LoadDataAsync()
    {
        var newData = await Task.Run(() =>
        {
            return _pageMstRepository.GetData().Select(entity => new PageMstViewModelEntity(entity));
        });

        lock (_lock)
        {
            Clear();
            foreach (var item in newData)
            {
                Add(item);
            }
        }
    }
}

このクラスでは、LoadDataAsyncメソッド内で_pageMstRepositoryから非同期にデータを取得し、lock文を使用してUIスレッドで安全にObservableCollectionを更新しています。

ViewModelの使用例

最後に、これらのクラスをViewModelで使用する例を示します。

public class MainViewModel : ViewModelBase
{
    private readonly PageMstCollection _pageMstCollection;

    public MainViewModel(IPageMstRepository pageMstRepository)
    {
        _pageMstCollection = new PageMstCollection(pageMstRepository);
        LoadData();
    }

    private async void LoadData()
    {
        await _pageMstCollection.LoadDataAsync();
        OnPropertyChanged(nameof(PageMstCollection));
    }

    public ObservableCollection<PageMstViewModelEntity> PageMstCollection => _pageMstCollection;
}

ViewModelでLoadDataAsyncメソッドを呼び出すことで、バックグラウンドでデータを非同期に読み込み、UIに反映できます。OnPropertyChangedメソッドを使用して、PageMstCollectionプロパティの変更を通知します。

これで、非同期でデータを更新するObservableCollectionを作成し、WPFアプリケーションで使用する方法がわかりました。