UIをコードでXAMLっぽく構築する方法

WPFSilverlight では、XAML で UI を記述するのが基本です。でも、どうしてもコードで記述せざるを得ない場合がまれにあります。たとえば、配置する要素がユーザーの設定内容で変わる場合とか。


だいぶ前に、C# のコードで XAML っぽく記述できる DSL を作ってみました。

でも、このような DSL を実装するのはひと苦労。もっと簡単な方法がいいですよね。例えば、オブジェクト初期化子とコレクション初期子を駆使すれば、XAML っぽく書けるのでは?


やってみました。

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

namespace CreateElementSample
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            // オブジェクト初期化子とコレクション初期化子を駆使して
            // XAML っぽく UI を構築する
            Content = new Grid()
            {
                RowDefinitions =
                {
                    new RowDefinition()
                    {
                        Height = GridLength.Auto,
                    },
                    new RowDefinition()
                    {
                        Height = new GridLength(1.0, GridUnitType.Star)
                    }
                },
                Children =
                {
                    CreateElement(()=>
                    {
                        var stackPanel = new StackPanel()
                        {
                            Orientation = Orientation.Horizontal,
                            Children =
                            {
                                new TextBox()
                                {
                                    Width = 100,
                                },
                                new Button()
                                {
                                    Content = "Test",
                                },
                            }
                        };
                        Grid.SetRow(stackPanel, 0);
                        return stackPanel;
                    }),
                    CreateElement(()=>
                    {
                        var dataGrid = new DataGrid()
                        {
                            Columns =
                            {
                                new DataGridTextColumn()
                                {
                                    Header = "ID",
                                },
                                new DataGridTextColumn()
                                {
                                    Header = "Name",
                                },
                            }
                        };
                        Grid.SetRow(dataGrid, 1);
                        return dataGrid;
                    }),
                },
            };
        }

        // 添付プロパティを設定するときに使うメソッド
        private T CreateElement<T>(Func<T> method)
        {
            return method();
        }
    }
}


添付プロパティはオブジェクト初期化子で設定できないので、ヘルパーメソッドを使って回避しました。要素の記述が XAML みたいに入れ子になっているから、親子関係がわかりやすいんじゃないでしょうか。