読者です 読者をやめる 読者になる 読者になる

しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

Xamarin.Forms で数値が含まれる範囲に応じて配色を切り替える

C# Windows ランタイムアプリ Xamarin XAML

本当はそろそろ Android にも進出しようと思っていたのですが、Xamarin のライセンス申請がなかなか進まず・・・

というわけでライセンスが発行されるまでしばし Xamarin.Forms であれこれ試してみました

Excel なんかで数値が含まれる範囲に応じてセルの配色を入れ替える条件付き書式がありますが、それを Xamarin.Forms でやってみました

用意したのは Converter

/// <summary>
/// 数値から配色に変換する Converter
/// </summary>
[ContentProperty("Ranges")]
public class RangeToColorConverter : IValueConverter
{
    /// <summary>
    /// ColorTypeConverter
    /// </summary>
    private static  readonly ColorTypeConverter Converter = new ColorTypeConverter();

    /// <summary>
    /// 数値範囲定義
    /// </summary>
    public List<RangeToColor> Ranges { get; set; }

    /// <summary>
    /// コンストラクタ
    /// </summary>
    public RangeToColorConverter()
    {
        this.Ranges = new List<RangeToColor>();
    }

    /// <summary>
    /// 数値から配色に変換します
    /// </summary>
    /// <param name="value">数値</param>
    /// <param name="targetType">対象の型</param>
    /// <param name="parameter">パラメータ</param>
    /// <param name="culture">カルチャ</param>
    /// <returns>配色</returns>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var color = Color.Transparent;
        var number = default(double);

        if (value is double)
        {
            number = (double) value;
        }
        else if (value != null)
        {
            double.TryParse(value.ToString(), out number);
        }

        var range = (from r in this.Ranges
            where r.From <= number && r.To >= number
            select r).FirstOrDefault();

        try
        {
            color = (Color)Converter.ConvertFrom(culture, range.Color);
        }
        catch (Exception)
        {
        }

        return color;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

/// <summary>
/// 数値範囲の記述クラス
/// </summary>
public class RangeToColor : BindableObject
{
    /// <summary>
    /// 数値範囲の最小値
    /// </summary>
    public double From { get; set; }

    /// <summary>
    /// 数値範囲の最大値
    /// </summary>
    public double To { get; set; }

    /// <summary>
    /// 変換後の色コード
    /// </summary>
    public string Color { get; set; }

    /// <summary>
    /// コンストラクタ
    /// </summary>
    public RangeToColor()
    {
        this.From = 0d;
        this.To = 0d;
        this.Color = @"#00FFFFFF";
    }
}

RangeToColor のコレクションを内包していて、指定範囲内に数値が含まれていれば対応する配色に変換するようにしています

これをおもむろに XAML に使います

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:b="clr-namespace:XamarinControl.Behaviors;assembly=XamarinControl"
             xmlns:c="clr-namespace:XamarinControl.Controls;assembly=XamarinControl"
             xmlns:cv="clr-namespace:XamarinControl.Converters;assembly=XamarinControl"
             xmlns:s="clr-namespace:XamarinControl.Selectors;assembly=XamarinControl"
             xmlns:vm="clr-namespace:XamarinControl.ViewModels;assembly=XamarinControl"
             xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib"
             x:Class="XamarinControl.Views.TopPage">

  <ContentPage.Resources>
    <ResourceDictionary>
      <cv:RangeToColorConverter x:Key="RangeToColorConverter">
        <cv:RangeToColor From="0" To="60" Color="Red"/>
        <cv:RangeToColor From="60" To="80" Color="Green"/>
        <cv:RangeToColor From="80" To="100" Color="Blue"/>
      </cv:RangeToColorConverter>
    </ResourceDictionary>
  </ContentPage.Resources>
  
  <ListView >
    <ListView.ItemsSource>
      <scg:List x:TypeArguments="x:Int32">
        <x:Int32>50</x:Int32>
        <x:Int32>70</x:Int32>
        <x:Int32>80</x:Int32>
        <x:Int32>100</x:Int32>
      </scg:List>
    </ListView.ItemsSource>
    <ListView.ItemTemplate>
      <DataTemplate>
        <ViewCell>
          <Grid Padding="20,10">
            <Label Text="{Binding StringFormat='{0} 点'}"
                   HorizontalOptions="Center"
                   VerticalOptions="Center"
                   TextColor="{Binding Converter={StaticResource RangeToColorConverter}}"
                   FontSize="50"/>
          </Grid>
        </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>

</ContentPage>

今回は横着して ViewModel すら用意せずに XAML で強引にデータを埋め込んでます

とにもかくにも上記のような XAML で実行すると

f:id:matatabi_ux:20150217222044p:plain

はい!さくっと点数に応じて色分けできましたね!