【Xamarin.Forms】TypeConverterの使い方
この記事は「Xamarin Advent Calendar 2015 - Qiita」の9日目です。
TypeConverterはXAMLでプロパティの値を指定する際、文字列から実際の方への変換を手助けしてくれます。(Binding時に登場するIValueConverterとは別物) Xamarin AC 5日目の記事で紹介したXFXamlAnimationsでもEasingプロパティなどで使われています。
例えば、XAML内で Padding="0,20,0,0"
や TextColor="Red"
と書くと、それぞれ Thicness
、 Color
に変換されます。これはビルトインされたTypeConverterのおかげです。
ビルトインTypeConverterが対応していない方への変換は独自に設定する必要があります。この記事ではその方法を解説します。
余談ですが、enum型はTypeConverterを使わなくても変換してくれるようです。(メンバ名、数値から変換可能)
サンプル
モデルケースとして、Labelコントロールを継承してColorThemeという独自プロパティを備えたMyLabelコントロールを作成します。
public class MyLabel : Label { #region ColorTheme BindableProperty public static readonly BindableProperty ColorThemeProperty = BindableProperty.Create<MyLabel, ColorTheme>(p => p.ColorTheme, default(ColorTheme), propertyChanged: (bindable, oldValue, newValue) => ((MyLabel)bindable).ColorTheme = newValue); public ColorTheme ColorTheme { get { return (ColorTheme)GetValue(ColorThemeProperty); } set { SetValue(ColorThemeProperty, value); ChangeColor(value); } } #endregion private void ChangeColor(ColorTheme theme) { if(theme == null) return; BackgroundColor = theme.BaseColor; TextColor = theme.AccentColor; } } public class ColorTheme { public Color AccentColor { get; set; } public Color BaseColor { get; set; } public static ColorTheme Dark { get { return new ColorTheme { AccentColor = Color.White, BaseColor = Color.Gray, }; } } public static ColorTheme Light { get { return new ColorTheme { AccentColor = Color.Black, BaseColor = Color.White, }; } } }
Viewです、ColorThemeは名前(Dark、Light)で指定したいのでとりあえず書いてみましょう。
<ContentPage.Content> <StackLayout VerticalOptions="Center"> <local:MyLabel Text="Dark" ColorTheme="Dark" /> <local:MyLabel Text="Light" ColorTheme="Light" /> </StackLayout> </ContentPage.Content>
このまま実行すると...
Xamarin.Forms.Xaml.XamlParseException Position 10:31. Cannot assign property "ColorTheme": type mismatch between "System.String" and "XFApp4.ColorTheme"
XAML解析時に「string型からColorTheme型へ変換できません」と怒られてしまいました。まぁ、そうなるな。
独自のTypeConverterを作る
ColorThemeのためのTypeConverterを用意しましょう。
public class ColorThemeTypeConverter : TypeConverter { #region implemented abstract members of TypeConverter public override bool CanConvertFrom(Type sourceType) { return sourceType == typeof(string); } public override object ConvertFrom(System.Globalization.CultureInfo culture, object value) { if(value == null) return null; if("Dark".Equals(value)) { return ColorTheme.Dark; } if("Light".Equals(value)) { return ColorTheme.Light; } throw new InvalidOperationException( string.Format("Conversion failed: {0} into {1}", value, typeof(ColorTheme))); } #endregion }
overrideすべきメソッドは2つ
bool CanConvertFrom(Type sourceType)
- XAMLからの変換に使う場合、string型であるかどうかを確認すればOKです。
object ConvertFrom(System.Globalization.CultureInfo culture, object value)
- 文字列を解析して適切なインスタンスを返しましょう。
次に、MyLabelに修正を加えましょう。ColorThemeプロパティにTypeConverterAttirbuteを付加してColorThemeTypeConverterが呼ばれるようにします。
public class MyLabel : Label { // 省略 // TypeConverterAttribureを付加 [TypeConverter(typeof(ColorThemeTypeConverter))] public ColorTheme ColorTheme { get { return (ColorTheme)GetValue(ColorThemeProperty); } set { SetValue(ColorThemeProperty, value); ChangeColor(value); } } // 省略 }
再度実行してみると...
無事、XAMLから指定したColorThemeが反映されました。やったね。