【Xamarin.Forms 2.1.0(プレビュー)】ControlTemplate
Xamarin.Forms 2.1.0 で ControlTemplate
が追加される予定です。
Xamarin.Forms 2.1.0-pre2 Released - Xamarin Forums
ControlTemplate は次のクラスで使用可能です。
ContentPage
ContentView
TemplatedPage
TemplatedView
TemplatedPage、TemplatedView が追加され、それに伴いContentPageの基底クラスがTemplatedPageへ、 ContentViewの基底クラスがTemplatedViewへ変更されます。
サンプル
TemplatedViewを継承してユーザーコントロールを作成します。ここにはUI定義が一切書かれていないことに注目してください。
using System; using Xamarin.Forms; using System.Windows.Input; namespace XFApp10 { public class LoginView : TemplatedView { public static readonly BindableProperty UserNameProperty = BindableProperty.Create("UserName", typeof(string), typeof(TemplateSamplePage), null, BindingMode.TwoWay); public string UserName { get { return (string)GetValue(UserNameProperty); } set { SetValue(UserNameProperty, value); } } public static readonly BindableProperty PasswordProperty = BindableProperty.Create("Password", typeof(string), typeof(TemplateSamplePage), null, BindingMode.TwoWay); public string Password { get { return (string)GetValue(PasswordProperty); } set { SetValue(PasswordProperty, value); } } public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(TemplateSamplePage), null); public ICommand Command { get { return (ICommand)GetValue(CommandProperty); } set { SetValue(CommandProperty, value); } } } }
LoginViewにセットするControlTemplateはApp.xamlで定義します。App.xamlを追加する方法は@omanukeさんのXamarin.FormsでApp.xamlを追加する方法 - omanuke-ekunamoの日記を参照で。
<?xml version="1.0" encoding="UTF-8"?> <Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="XFApp10.App"> <Application.Resources> <ResourceDictionary> <!-- LoginViewの見た目 --> <ControlTemplate x:Key="LoginViewTemplate"> <StackLayout VerticalOptions="CenterAndExpand" Spacing="20" Padding="20" > <Entry Text="{TemplateBinding UserName, Mode=TwoWay}" Placeholder="UserName" /> <Entry Text="{TemplateBinding Password, Mode=TwoWay}" Placeholder="Password" /> <Button Command="{TemplateBinding Command}" Text="Click Here To Log In" /> </StackLayout> </ControlTemplate> </ResourceDictionary> </Application.Resources> </Application>
LoginViewのプロパティとテンプレートの紐付けには TemplateBinding を使用します。これも新しい構文です、通常のBinding構文とは別なので注意。
ViewModelのプロパティとバインドしたい場合(ControlTemplatesでするべきではないと思いますが) {TemplateBinding BindingContext.Hoge}
のようにBindingContextを経由することでアクセス可能です。
LoginViewを利用する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:local="clr-namespace:XFApp10;assembly=XFApp10" x:Class="XFApp10.MyPage" > <ContentPage.Content> <local:LoginView ControlTemplate="{StaticResource LoginViewTemplate}" UserName="{Binding UserName}" Password="{Binding Password}" Command="{Binding Command}" /> </ContentPage.Content> </ContentPage>
こちらでViewModelとバインドすればControlTemplateとViewModelが繋がります。
結果はこのようになります。
WPFとの比較
WPFではButtonなど既存コントロールの見た目をカスタムする際にControlTemplateがよく使用されますが、Xamarin.Formsの場合はControlTemplateに対応したクラスは最初に説明した4つしかありません。 なので、基本的にユーザーコントロールを作成する際に使用する物という認識で良いでしょう。 縦向き用、横向き用のレイアウトをControlTemplateで用意して切り変えるという使い方はアリかも。
Xamarin.FormsはMerged Dictionaryに対応していません。(バージョン2.1.0プレビュー時点) そのためコントロール毎にテンプレートを定義したResourceDictionaryファイルを用意する、といった使い方ができません。