コードで WPF の UI を構築するための DSL

XAML に比べ、コードで WPF の UI を構築するのはかなり面倒です。XAML だと1行で済んだことが、コードだと数行書かないといけません。

UI は全部 XAML で書きたいけど、悲しいことに、仕事ではコードで書く事が多いです。せめて、コードで XAML に近い書き方ができればいいのに…。

そこで、コードで WPF の UI を構築するための DSL が作れないか、ちょっと試してみました。サンプルがこちら(DSL というのも申し訳ない)。

using System;
using System.Windows;
using System.Windows.Controls;

namespace XamlSample
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            // XAML みたいに記述できる。
            this.Grid()
                    .RowDefenitions()
                        .RowDefenition()
                        .RowDefenition()
                    .End()
                    .With<TextBox>(t => { t.Text = "text"; Grid.SetRow(t, 0); })
                    .With<Button>(b => { b.Content = "OK"; Grid.SetRow(b, 1); })
                .End();
        }
    }

    public static class WindowExtension
    {
        public static GridElement Grid(this Window self)
        {
            return new GridElement(self);
        }
    }

    public class GridElement
    {
        private Grid _grid;
        private Window _window;

        public GridElement(Window window)
        {
            _window = window;
            _grid = new Grid();
            _window.Content = _grid;
        }

        public RowDefenitionsElement RowDefenitions()
        {
            return new RowDefenitionsElement(_grid, this);
        }

        public Window End()
        {
            return _window;
        }

        public GridElement With<T>(Action<T> init) where T : UIElement, new()
        {
            T obj = new T();
            init(obj);
            _grid.Children.Add(obj);
            return this;
        }
    }

    public class RowDefenitionsElement
    {
        private Grid _grid;
        private GridElement _gridElement;

        public RowDefenitionsElement(Grid grid, GridElement gridElement)
        {
            _grid = grid;
            _gridElement = gridElement;
        }

        public RowDefenitionsElement RowDefenition()
        {
            _grid.RowDefinitions.Add(new RowDefinition());
            return this;
        }

        public GridElement End()
        {
            return _gridElement;
        }
    }
}

コントロールのプロパティを設定するときに、ラムダ式を使ってみました。一見、XAML っぽい。実用レベルではないけど、ちゃんと作り込むのも面白いかも。

まあ、既に誰かが作っているなら、それを利用しますけどね。