 
Xamarin逆引きTips
Xamarin.Formsでビヘイビアーを使用するには?
サブクラス化することなく、UIコントロールに機能を追加できる「ビヘイビアー」の基本的な使い方を説明する。
Xamarin.Formsのバージョン1.3以降で追加された新機能の一つにビヘイビアーがある。ビヘイビアーを使用すると、サブクラス化することなく、UIコントロールに機能を追加できる。
今回は、このビヘイビアーの利用方法について解説する。
- *1 なお本Tipsは、Windows上でVisual Studio 2013を使用してXamarin.Forms開発をすることを前提としている(※編集部注: Mac上のXamarin Studioでも同様の手順で、本稿の内容が実現できることは確認している)。使用しているXamarin.Formsのバージョンは、プロジェクト作成時に利用されている「1.3.1.6296」である。
1. シナリオ
最初に、電子メールアドレスの入力と[送信]ボタンというような簡単なUI画面を題材として、入力内容が適正かどうかをテキスト色の変化で視覚的にユーザーに伝えるようにする。
続いて、入力の内容が適正なときだけ、[送信]ボタンが押せるように拡張する。
2. Xamarin.Formsプロジェクトを作成する
メニューバーの[ファイル]-[新規作成]-[プロジェクト]から表示したダイアログで、[テンプレート]-[Visual C#]-[Mobile Apps]-[Blank App (Xamarin.Forms Portable)]を選択し、名前を「BehaviorSample」として[OK]ボタンを押す。
3.テキスト入力とボタン
最初に、ビヘイビアーを適用するための簡単な入力画面を作成する。
テキスト入力とボタンを配置した画面を表示するには、App.csファイルを以下のように修正する。
| using Xamarin.Forms; namespace BehaviorSample {   public class App : Application {     public App() {       MainPage = new MyPage();     }   ……省略……   }   class MyPage : ContentPage {     public MyPage() {       var button = new Button { // <-1         Text = "Send",         HorizontalOptions = LayoutOptions.Center,       };       var entry = new Entry { // <-2         WidthRequest = 200,         Placeholder = "user@example.com",         HorizontalOptions = LayoutOptions.Center,       };       Content = new StackLayout { // <-3         Padding = new Thickness(0,Device.OnPlatform(40,20,20),0,0),         Children = { entry, button }       };     }   } } | 
 最初に、Buttonコントロール(1)と、Entryコントロール(2)を生成している。
 Buttonコントロールには、「送信」を意味するようにSendと表示し、Entryコントロールには、プレースホルダーとしてuser@example.comを表示して電子メールアドレスの入力を促すようにする。また、どちらも画面の中央に配置されるようにHorizontalOptionsプロパティは、LayoutOptions.Centerとしている。
 生成した2つのコントロールは、StackLayoutで上下になるように配置している(3)。
このコードを実行すると次のような画面になる。
4. 拡張ビヘイビアークラス
 ビヘイビアーを実装するには、Behaviorクラス(Xamarin.Forms名前空間)を継承した拡張ビヘイビアークラスを定義する必要がある。
拡張ビヘイビアークラスを追加したApp.csファイルは、次のようになる。
| using System.Text.RegularExpressions; ……省略…… namespace BehaviorSample {   class MyPage : ContentPage {     public MyPage() {       ……省略……       var entry = new Entry {          WidthRequest = 200,         Placeholder = "user@example.com",         HorizontalOptions = LayoutOptions.Center,         Behaviors = { new EmailBehavior() } // <-1       };       ……省略……     }   }   public class EmailBehavior : Behavior<Entry> { // <-2     private readonly Regex _regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"); // <-3     protected override void OnAttachedTo(Entry bindable) { // <-4       bindable.TextChanged += CheckEmail;     }     protected override void OnDetachingFrom(Entry bindable) { // <-5       bindable.TextChanged -= CheckEmail;     }     private void CheckEmail(object sender, TextChangedEventArgs e) {  // <-6       //文字列がEmailとして正しいかどうかのチェック       var m = _regex.Match(e.NewTextValue);       //正かどうかによってテキストの色を変化させる       ((Entry) sender).TextColor = m.Success ? Color.Default : Color.Red;     }   } } | 
 2では、Behaviorクラスを継承した拡張ビヘイビアークラス(ここでは、クラス名をEmailBehaviorとした)を作成している。このとき、このビヘイビアーを適用するコントロール(ここでは、Entryコントロール)の型を指定する必要がある。
 Behaviorクラスを継承すると、OnAttachedToメソッド(4)および、OnDetachingFromメソッド(5)のオーバーライドが可能になる。これらのメソッドは、それぞれ、対象コントロール(=Entryコントロール)に、このビヘイビアーが適用された時および、削除された時に呼び出される。このため、ビヘイビアーで使用するオブジェクトの生成および、破棄などの処理が必要なときは、ここに記述することになる。サンプルコードでは、イベントへのハンドラー(CheckEmailメソッド)の追加と削除を行っている。
 イベントハンドラーとして用意したCheckEmailメソッドは、文字列が電子メールアドレスとして適切であるか否かを判断してEntryコントロールのテキスト色を変化させるものである(6)。なお、適正かどうかの判断は、正規表現クラスを使用した(3)。
 最後に、定義したビヘイビアーの適用であるが、これは、対象コントロールのBehaviorsプロパティに追加することで行う(1)。
このコードを実行すると次のような画面になる。
5. 別コントロールとの連携
ビヘイビアーの基本的な役割は、既存のコントロールを拡張することであるが、応用として、この拡張ビヘイビアークラスに状態を表すプロパティなどを実装して、他のコントロールと連携することも可能である。
状態を表すプロパティを実装した拡張ビヘイビアークラスは次のようになる。
| ……省略…… namespace BehaviorSample {   ……省略……   public class EmailBehavior : Behavior<Entry> {      public bool IsValid { get; private set; } // <-1     ……省略……     private void CheckEmail(object sender, TextChangedEventArgs e) {         var m = _regex.Match(e.NewTextValue);       ((Entry) sender).TextColor = m.Success ? Color.Default : Color.Red;       IsValid = m.Success; // <-2     }   } } | 
 1では、電子メールアドレスとして有効かどうかの状態を表すプロパティ(IsValid)を追加した。
そして、判定した結果を、このプロパティに設定している(2)。
このプロパティ値を使用して、ボタンの有効/無効を変化させるには、App.csファイルを以下のように修正する。
| ……省略…… namespace BehaviorSample {   ……省略……   class MyPage : ContentPage {     public MyPage() {       var emailBehavior = new EmailBehavior(); // <-1       var button = new Button {         Text = "Send",         HorizontalOptions = LayoutOptions.Center,         IsEnabled = emailBehavior.IsValid // <-2       };       var entry = new Entry {         WidthRequest = 200,         Placeholder = "user@example.com",         HorizontalOptions = LayoutOptions.Center,         Behaviors = { emailBehavior }       };       entry.TextChanged += (sender, args) =>{         button.IsEnabled = emailBehavior.IsValid; // <-3       };       Content = new StackLayout {         Padding = new Thickness(0, Device.OnPlatform(40, 20, 20), 0, 0),         Children = {entry, button}       };     }   }   ……省略…… } | 
拡張ビヘイビアークラスは、変数として生成する(1)。
 そして、Buttonオブジェクトの有効/無効は、この変数のプロパティ値で初期化した(2)。
 また、Entryコントロールのテキスト変化時も、Buttonオブジェクトの有効/無効が変化するようにした(3)。
このコードを実行すると次のような画面になる。
電子メールアドレスとして不完全な場合(左)は、無効、完全となった時点(右)で有効になる。
【コラム】進化するXamarin.Forms
Xamarin.Formsは、昨年5月、Xamarin 3と共に新たに登場したフレームワークであり、まだ、誕生して1年にも満たない。しかし、誕生後すごい勢いで進化を遂げており、今回紹介したビヘイビアーも、昨年末に追加された機能の1つである。
つい先日、アナウンスされたXamarin.Forms.Windows(2015年3月24日現在はアルファ版)では、新たに、Windows Phone RT(※「RT」とはSilverlightアプリではない「WinRTアプリ」のこと)やストアアプリも同時に開発できるようになった。
6. まとめ
今回は、既存のコントロールをサブクラス化することなく、機能拡張できるビヘイビアーについて解説した。また、応用として、状態を表すプロパティなどによる、他のコントロールと連携する方法についても併せて紹介した。
ビヘイビアーによって、よりユーザーに優しい、また、フールプルーフなUI構築が可能になる。
※以下では、本稿の前後を合わせて5回分(第40回~第44回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
 
40. Xamarin.Formsで地図の現在位置やピンの表示、縮尺や地図タイプの変更を行うには?(Xamarin.Forms.Maps使用)
Xamarin.Forms.Mapsコントロールで利用可能な機能として、「現在位置」や「衛星写真」「ピン立て」「スライダーコントロールによる地図の拡大・縮小」などを解説する。
 
43. MvvmCrossでコマンドバインディングをするには?
MvvmCrossでは、画面でのイベント発生をViewModelに通知するためにコマンドバインディングを使用する。iOS/Androidにおける、その基本的な実装方法を説明する。
 
44. Xamarin.FormsでListViewのコンテキストアクションを使用するには?
リストの1つをスライド(iOS)もしくは長押し(Android)されたらメニューを表示する「コンテキストアクション」の基本的な使い方を説明する。





 
  
  
  
  
  
  
  
  
  
  
  
  
 
