- はじめに:「ObservableCollection変換」は“画面とコレクションをつなぐ橋”
- ObservableCollection とは何か、なぜ必要なのか
- LINQ 結果を ObservableCollection に変換する基本
- ユーティリティ拡張メソッド ToObservableCollection を作る
- 実務での使いどころ 1:検索結果を画面に出す
- 実務での使いどころ 2:マスタ読み込み → 画面バインド
- 実務での使いどころ 3:別型への変換+ObservableCollection
- ObservableCollection変換で気をつけたいこと
- まとめ:「ObservableCollection変換ユーティリティ」は“LINQ と画面をつなぐ変換アダプタ”
はじめに:「ObservableCollection変換」は“画面とコレクションをつなぐ橋”
業務アプリ(特に WPF / MAUI / WinUI など)を書くと、List<T> や IEnumerable<T> でデータを持っているのに、
画面バインディングでは ObservableCollection<T> が欲しくなる、という場面が必ず出てきます。
LINQ でデータを加工したあと、その結果をそのまま画面に出したい
検索結果やフィルタ結果を、画面のリストに反映したい
マスタデータを読み込んで、画面側のコレクションに流し込みたい
こういうときに使うのが「ObservableCollection変換」です。
つまり、
IEnumerable<T> / List<T> → ObservableCollection<T>
への変換を、ユーティリティとしてサッと書けるようにしておく、という話です。
ここから、
ObservableCollection がなぜ必要なのか
LINQ 結果を ObservableCollection に変換する基本パターン
拡張メソッドとして ToObservableCollection を用意する
実務での使いどころ(検索結果・フィルタ結果・マスタ読み込み)
を、初心者向けにかみ砕いて説明していきます。
ObservableCollection とは何か、なぜ必要なのか
List との一番大きな違い:「変化を通知してくれる」
ObservableCollection<T> は、ざっくり言うと「通知機能付きの List」です。
List<T>
要素の追加・削除はできるが、「変わったよ」とは誰にも教えない
ObservableCollection<T>
要素の追加・削除があると、「変わったよ」というイベントを発行してくれる
WPF や MAUI などのデータバインディングは、この「変わったよ通知」を使って画面を自動更新しています。
画面にバインドするコレクションが List<T> だと、
中身を変えても画面は勝手には更新されません。ObservableCollection<T> なら、要素を追加・削除した瞬間に画面が追従してくれます。
ここでの重要ポイントは、「画面にバインドするコレクションは、基本的に ObservableCollection<T> にしておくと幸せになりやすい」ということです。
LINQ 結果を ObservableCollection に変換する基本
まずは素朴な書き方から
例えば、ユーザー一覧を LINQ で絞り込んだあと、その結果を画面に出したいとします。
using System;
using System.Collections.ObjectModel;
using System.Linq;
public class User
{
public int Id { get; set; }
public string Name { get; set; } = "";
}
var allUsers = new[]
{
new User { Id = 1, Name = "Alice" },
new User { Id = 2, Name = "Bob" },
new User { Id = 3, Name = "Charlie" },
};
C#「名前に a を含むユーザーだけを画面に表示したい」という場合、LINQ でこう絞ります。
var filtered = allUsers
.Where(x => x.Name.Contains("a", StringComparison.OrdinalIgnoreCase));
C#この filtered は IEnumerable<User> です。
これを ObservableCollection<User> に変換するには、こう書けます。
var observable = new ObservableCollection<User>(filtered);
C#これで、observable を画面にバインドすれば、
「LINQ で絞り込んだ結果」がそのまま画面に出せます。
ここでの重要ポイントは、「ObservableCollection<T> はコンストラクタで IEnumerable<T> を受け取れる」ということです。
つまり、「LINQ の結果 → そのまま渡して ObservableCollection にする」という流れが自然に書けます。
ユーティリティ拡張メソッド ToObservableCollection を作る
毎回 new ObservableCollection<T>(…) と書くのは少しダルい
LINQ のチェーンの最後に、毎回こう書くのは少し長いです。
var observable = new ObservableCollection<User>(
allUsers.Where(x => 条件)
);
C#そこで、「ToList() と同じノリで ToObservableCollection() が欲しい」という気持ちになります。
自分で拡張メソッドを 1 本用意しておきましょう。
using System.Collections.Generic;
using System.Collections.ObjectModel;
public static class ObservableCollectionExtensions
{
public static ObservableCollection<T> ToObservableCollection<T>(
this IEnumerable<T> source)
{
return new ObservableCollection<T>(source);
}
}
C#使い方はこうです。
var observable = allUsers
.Where(x => x.Name.Contains("a", StringComparison.OrdinalIgnoreCase))
.ToObservableCollection();
C#ここでの重要ポイントは、「ToObservableCollection() という名前だけで、“画面バインド用のコレクションにしている”ことが一目で分かる」ということです。ToList() と同じ感覚で使えるので、チーム内でもすぐに浸透します。
実務での使いどころ 1:検索結果を画面に出す
検索条件に応じて ObservableCollection を差し替える
例えば、WPF の ViewModel で、こういうプロパティを持っているとします。
public ObservableCollection<User> Users { get; }
= new ObservableCollection<User>();
C#検索ボタンを押したときに、LINQ で絞り込んで Users を差し替えたい。
そんなとき、こう書きがちです。
void Search(string keyword)
{
Users.Clear();
var filtered = allUsers
.Where(x => x.Name.Contains(keyword, StringComparison.OrdinalIgnoreCase));
foreach (var u in filtered)
{
Users.Add(u);
}
}
C#これはこれでアリですが、ToObservableCollection を使うと、もう少しスッキリ書けます。
void Search(string keyword)
{
var filtered = allUsers
.Where(x => x.Name.Contains(keyword, StringComparison.OrdinalIgnoreCase))
.ToObservableCollection();
Users = filtered; // プロパティを set できる形にしておく
}
C#あるいは、Users を set できない設計なら、
一時的に ObservableCollection を作ってから中身を入れ替える、という手もあります。
void Search(string keyword)
{
var filtered = allUsers
.Where(x => x.Name.Contains(keyword, StringComparison.OrdinalIgnoreCase))
.ToObservableCollection();
Users.Clear();
foreach (var u in filtered)
{
Users.Add(u);
}
}
C#ここでの重要ポイントは、「LINQ で作った“新しい結果セット”を、ObservableCollection として一度に扱える」ということです。ToObservableCollection があると、「LINQ の世界」と「画面バインドの世界」の橋渡しがとても楽になります。
実務での使いどころ 2:マスタ読み込み → 画面バインド
起動時にマスタを読み込んで、そのまま画面に出す
例えば、起動時に DB から商品マスタを読み込んで、画面のリストに出したいケース。
public ObservableCollection<Item> Items { get; }
= new ObservableCollection<Item>();
void Load()
{
var allItems = _itemRepository.GetAll(); // 戻り値は IEnumerable<Item>
var observable = allItems
.OrderBy(x => x.Code)
.ToObservableCollection();
Items.Clear();
foreach (var item in observable)
{
Items.Add(item);
}
}
C#ここでの重要ポイントは、「DB から取ってきた IEnumerable<T> に対しても、LINQ で加工してから ToObservableCollection すれば、そのまま画面に流し込める」ということです。
「データ取得 → LINQ で整形 → ObservableCollection に変換 → 画面へ」というパイプラインが、きれいに一本線で書けます。
実務での使いどころ 3:別型への変換+ObservableCollection
DTO や ViewModel に変換してからバインドしたい
業務では、「DB のエンティティそのもの」ではなく、
画面用の ViewModel や DTO に変換してからバインドしたいことが多いです。
public class UserViewModel
{
public int Id { get; set; }
public string DisplayName { get; set; } = "";
}
C#var userViewModels = allUsers
.Select(u => new UserViewModel
{
Id = u.Id,
DisplayName = $"{u.Id}: {u.Name}"
})
.ToObservableCollection();
C#ここでの重要ポイントは、「Select で別型に変換した結果にも、そのまま ToObservableCollection をつなげられる」ということです。
LINQ の変換と ObservableCollection 変換を、自然なチェーンとして書けます。
ObservableCollection変換で気をつけたいこと
「変換したあとに追加・削除するかどうか」を意識する
ToObservableCollection で変換したコレクションは、もちろんあとから Add / Remove できます。
ただし、
一度きりの表示用(検索結果を出して終わり)
その後は中身を変えない
という用途なら、ToList() でも足りる場面もあります。
逆に、
画面上で行の追加・削除をさせたい
別の処理からコレクションを更新したい
といった場合は、ObservableCollection にしておく意味が大きくなります。
ここでの重要ポイントは、「“本当に画面と一緒に動的に変わる必要があるか”を考えてから ObservableCollection にする」ということです。
なんでもかんでも ObservableCollection にすると、逆に設計が重くなることもあります。
まとめ:「ObservableCollection変換ユーティリティ」は“LINQ と画面をつなぐ変換アダプタ”
ObservableCollection変換の本質は、
LINQ で気持ちよくデータを加工したあと、
その結果をそのまま画面にバインドできる形に変える
ことです。
押さえておきたいポイントを整理すると、
画面バインドには ObservableCollection<T> が向いている(変更通知が飛ぶ)new ObservableCollection<T>(IEnumerable<T>) で LINQ 結果をそのまま変換できるToObservableCollection() 拡張メソッドを 1 本用意しておくと、チェーンの最後に自然に書ける
検索結果・マスタ読み込み・DTO/ViewModel 変換など、業務での出番はかなり多い
「本当に動的更新が必要なところ」にだけ ObservableCollection を使う、というメリハリも大事
ここまで腹落ちしていれば、
「LINQ で作った結果をどう画面に渡すか」で迷う時間が減って、
“データの流れを意識して設計できる C# エンジニア”に一歩近づけます。
