しっぽを追いかけて

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

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

Xamarin.Forms の Picker の選択肢をデータバインドしたい

ひょんなことから Xamarin.Forms の Picker コントロールを使いたくなったので、下記のように XAML を記述してみました

 <Picker Items="{Binding ColorLabelSelection}"
         SelectedIndex="{Binding SelecedIndex, Mode=TwoWay}"/>

これを実行すると・・・

f:id:matatabi_ux:20150501170433p:plain

エラー!!

Binding を string に変換できない・・・

どうやら Picker.Items の選択肢のプロパティはバインディングできないようです・・・なんでやねん!

仕方がないので Picker を継承した BindablePicker クラスを作りました

/// <summary>
/// Binding 可能な Picker
/// </summary>
public class BindablePicker : Picker
{
    /// <summary>
    /// ItemsSource の BindableProperty
    /// </summary>
    public readonly static BindableProperty ItemsSourceProperty = BindableProperty.Create<BindablePicker, IEnumerable>(
        o => o.ItemsSource,
        default(IEnumerable),
        BindingMode.Default,
        null,
        OnItemsSourceChanged);

    /// <summary>
    /// ItemsSource の CLR プロパティ
    /// </summary>
    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)this.GetValue(ItemsSourceProperty); }
        set { this.SetValue(ItemsSourceProperty, value); }
    }

    /// <summary>
    /// ItemsSource の変更イベントハンドラ
    /// </summary>
    /// <param name="bindable">イベント発行者</param>
    /// <param name="oldValue">古い値</param>
    /// <param name="newValue">新しい値</param>
    private static void OnItemsSourceChanged(BindableObject bindable, IEnumerable oldValue, IEnumerable newValue)
    {
        var picker = bindable as BindablePicker;
        picker.Items.Clear();
        if (newValue == null)
        {
            return;
        }

        foreach (var item in newValue)
        {
            picker.Items.Add(item.ToString());
        }
    }
}

ItemsSource という BindableProperty を追加しただけ

XAML も書き換えます

 <c:BindablePicker ItemsSource="{Binding ColorLabelSelection}"
                   SelectedIndex="{Binding SelecedIndex, Mode=TwoWay}"/>

これで実行すれば、選択肢もバインディングできたしちゃんと動きました