SourceChord

C#とXAML好きなプログラマの備忘録。最近はWPF系の話題が中心です。

XamlReader/XamlWriterでXAMLを読み書き

XamlReaderクラスとXamlWriterクラスを使うことで、簡単にXAMLの読み書きができます。
ということで、さっそく使い方。

XamlWriterでWPFのコントロールとかをXAMLとして出力

XamlWriterにオブジェクトを渡すと、XAML形式のテキストを取得できます。
とりあえず、PageにGridを追加。Gridを2×2に分割してButtonを追加したものを用意し、このPageをXamlWriterで出力してみました。

サンプルコード
var page = new Page();
var grid = new Grid();
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());

var button = new Button() { Content = "test" };
Grid.SetColumn(button, 1);
Grid.SetRow(button, 1);
grid.Children.Add(button);

page.Content = grid;

// XAMLで書き出し
var text = XamlWriter.Save(page);
File.WriteAllText(@"C:\temp\test.xaml", text);
出力結果
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"><Grid><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition /></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition /><RowDefinition /></Grid.RowDefinitions><Button Grid.Column="1" Grid.Row="1">test</Button></Grid></Page>

しかし、これで出力されるXAMLは、改行を含まず1行になっていて、
ファイルなどに書き出して読むには、読みにくい形となっています。
どうせテキストに落とすなら、読みやすい形にしたい。

XAMLファイルをフォーマットして出力

以下のサイトを参考に、XAMLのフォーマットをしてみました。
http://stackoverflow.com/questions/1123718/format-xml-string-to-print-friendly-xml-string

XAMLXML形式のテキストなので、XDocumentを使ってXMLとして読み取ってから文字列に変換してます。
自分で下手に文字列をパースしてXAMLの整形をするよりも、こっちの方が信頼できそう。

XAMLを整形してから書き出し
private void Button_Click(object sender, RoutedEventArgs e)
{
    var page = new Page();
    var grid = new Grid();
    grid.ColumnDefinitions.Add(new ColumnDefinition());
    grid.ColumnDefinitions.Add(new ColumnDefinition());
    grid.RowDefinitions.Add(new RowDefinition());
    grid.RowDefinitions.Add(new RowDefinition());

    var button = new Button() { Content = "test" };
    Grid.SetColumn(button, 1);
    Grid.SetRow(button, 1);
    grid.Children.Add(button);

    page.Content = grid;

    // XAMLで書き出し
    var text = XamlWriter.Save(page);
    text = FormatXml(text);
    File.WriteAllText(@"C:\temp\test.xaml", text);
}

string FormatXml(String Xml)
{
    try
    {
        XDocument doc = XDocument.Parse(Xml);
        return doc.ToString();
    }
    catch (Exception)
    {
        return Xml;
    }
}
出力結果
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition />
      <RowDefinition />
    </Grid.RowDefinitions>
    <Button Grid.Column="1" Grid.Row="1">test</Button>
  </Grid>
</Page>

XamlReaderで読み込み

XamlWriterでの出力と同じように、XamlReaderを使うとXAMLファイルの読み込みができます。
前述のXamlWriterで出力したファイルを、XamlReaderで読み込んでみました。
読み込んだ結果のPageインスタンスを、ウィンドウに用意したFrameに設定して表示しています。

XAMLの読み込みテスト
private void Button_Click(object sender, RoutedEventArgs e)
{
    var page = new Page();
    var grid = new Grid();
    grid.ColumnDefinitions.Add(new ColumnDefinition());
    grid.ColumnDefinitions.Add(new ColumnDefinition());
    grid.RowDefinitions.Add(new RowDefinition());
    grid.RowDefinitions.Add(new RowDefinition());

    var button = new Button() { Content = "test" };
    Grid.SetColumn(button, 1);
    Grid.SetRow(button, 1);
    grid.Children.Add(button);

    page.Content = grid;

    // XAMLで書き出し
    var text = XamlWriter.Save(page);
    text = FormatXml(text);
    File.WriteAllText(@"C:\temp\test.xaml", text);

    // XAMLから読み込み
    Page readPage;
    using (var stream = File.Open(@"C:\temp\test.xaml", FileMode.Open))
    {
        readPage = XamlReader.Load(stream) as Page;
    }

    frame.Content = readPage;
}

string FormatXml(String Xml)
{
    try
    {
        XDocument doc = XDocument.Parse(Xml);
        return doc.ToString();
    }
    catch (Exception)
    {
        return Xml;
    }
}


XamlWriter/XamlReaderで任意のオブジェクトのシリアライズ

XamlWriter/XamlReaderでは、WPFなどで用いるコントロールだけでなく、任意のCLRオブジェクトの書き出し/読み込みもできます。

サンプルコード
    public class SampleData
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public double Data { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var data = new SampleData()
            {
                Name = "hoge",
                Age = 20,
                Data = 0.5
            };
            // XAML形式で書き出し
            var text = XamlWriter.Save(data);
            text = FormatXml(text);
            System.IO.File.WriteAllText(@"C:\temp\test.xaml", text);

            SampleData readData;
            using (var stream = File.Open(@"C:\temp\test.xaml", FileMode.Open))
            {
                readData = XamlReader.Load(stream) as SampleData;
            }

            Console.WriteLine(readData.Name);
            Console.WriteLine(readData.Age);
            Console.WriteLine(readData.Data);
        }


        static string FormatXml(String Xml)
        {
            try
            {
                XDocument doc = XDocument.Parse(Xml);
                return doc.ToString();
            }
            catch (Exception)
            {
                return Xml;
            }
        }
    }
出力結果
hoge
20
0.5
続行するには何かキーを押してください . . .