亀岡的プログラマ日記

京都のベッドタウン、亀岡よりだらだらとお送りいたします。

【ゆるぼ】コントロールの列挙を今風に書く。【つっこみ】

なんとなく、WindowsForms内のコントロールを全列挙する場面があって、再帰的に見るんだったよなぁ、と軽く検索してこれにたどりつきました。

コードはこんな感じ。

public Control[] GetAllControls(Control top)
{
  ArrayList buf = new ArrayList();
  foreach (Control c in top.Controls)
  {
    buf.Add(c);
    buf.AddRange(GetAllControls(c));
  }
  return (Control[])buf.ToArray(typeof(Control));
}

いやはや、時代を感じますね。今風にLinq使って書くと、こんな感じかなぁ、と書いたのがこちら。

static IEnumerable<Control> EnumurateAllControl(Control root)
{
    yield return root;
    foreach (var ctrl in root.Controls.Cast<Control>().SelectMany(c => EnumurateAllControl(c)))
    {
        yield return ctrl;
    }
}

IEnumerableによるコルーチンと、ラムダ式、そしてLinq。随分とシンプルに書けるようになったなぁとしみじみ。

んで、WPFでも同じような場面が必要で、書いてみたのがこちら。

static IEnumerable<System.Windows.DependencyObject> EnumurateAllElement(System.Windows.DependencyObject root)
{
    yield return root;
    foreach (var element in GetChilren(root).SelectMany(ele => EnumurateAllElement(ele)))
    {
        yield return element;
    }
}

static IEnumerable<System.Windows.DependencyObject> GetChilren(System.Windows.DependencyObject root)
{
    for (int i = 0; i < System.Windows.Media.VisualTreeHelper.GetChildrenCount(root); i++)
    {
        yield return System.Windows.Media.VisualTreeHelper.GetChild(root, i);
    }
}

VisualTreeHelperは、GetCountで個数取得してforでまわさせるというWinAPIのような使い心地。どうしてこんなの作っちゃったのよ・・・。やっぱりVisualTreeHelperを使うのは邪悪ってことなのか!?