Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

WPFのXAMLのTypeConverterお試し

$
0
0

WPFのXAMLではTypeConverterを自作して文字列から、オブジェクトを作るようなことが簡単にできるようになっています。ということで簡単に試してみました。XAMLからオブジェクトへの変換にはTypeConverterクラスのConvertFromメソッドとCanConvertFromメソッドを実装していれば問題なさそう。

今回は以下のようなPersonクラスで

publicclass Person
{
    publicstring Name { get; set; }
    public Person Child { get; set; }
}

Tanaka->Kimura->Hoge->Fooみたいに入力するとNameがTnakaのPersonを作って、そのChildにNameがKimuraのPersonを作って、そのChildに…(略)となるようなTypeConverterを作りました。->で区切って組み立てていくだけですので簡単です。

publicclass PersonTypeConverter : TypeConverter
{
    publicoverridebool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string);
    }

    publicoverrideobject ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, objectvalue)
    {
        var text = (string)value;
        var people = text
            .Split(new[] { "->" }, StringSplitOptions.None)
            .Select(s => s.Trim())
            .Select(s => new Person { Name = s })
            .ToArray();
        people
            .Aggregate((parent, child) =>
            {
                parent.Child = child;
                return child;
            });
        return people.First();
    }
}

このコンバータをPersonクラスにつけます。

[TypeConverter(typeof(PersonTypeConverter))]
publicclass Person
{
    publicstring Name { get; set; }
    public Person Child { get; set; }
}

System.Xamlを参照してレッツパース。

class Program
{
    staticvoid Main(string[] args)
    {
        var xaml = @"<Person xmlns='clr-namespace:ConsoleApplication3;assembly=ConsoleApplication3'                Name='Tanaka taro'                Child='Tanaka goro->Tanaka jiro->Tanaka hoge->Tnaka foo' />";

        var p = XamlServices.Parse(xaml) as Person;
        while (p != null)
        {
            Console.WriteLine("Name: {0}", p.Name);
            p = p.Child;
        }
    }
}

実行するといい感じに表示されます。

Name: Tanaka taro
Name: Tanaka goro
Name: Tanaka jiro
Name: Tanaka hoge
Name: Tnaka foo

コード全体

最後にコード全体をのせておきます。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xaml;

namespace ConsoleApplication3
{
    class Program
    {
        staticvoid Main(string[] args)
        {
            var xaml = @"<Person xmlns='clr-namespace:ConsoleApplication3;assembly=ConsoleApplication3'                    Name='Tanaka taro'                    Child='Tanaka goro->Tanaka jiro->Tanaka hoge->Tnaka foo' />";

            var p = XamlServices.Parse(xaml) as Person;
            while (p != null)
            {
                Console.WriteLine("Name: {0}", p.Name);
                p = p.Child;
            }
        }
    }

    [TypeConverter(typeof(PersonTypeConverter))]
    publicclass Person
    {
        publicstring Name { get; set; }
        public Person Child { get; set; }
    }

    publicclass PersonTypeConverter : TypeConverter
    {
        publicoverridebool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string);
        }

        publicoverrideobject ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, objectvalue)
        {
            var text = (string)value;
            var people = text
                .Split(new[] { "->" }, StringSplitOptions.None)
                .Select(s => s.Trim())
                .Select(s => new Person { Name = s })
                .ToArray();
            people
                .Aggregate((parent, child) =>
                {
                    parent.Child = child;
                    return child;
                });
            return people.First();
        }
    }
}

Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>