2016年4月28日木曜日

macのdylibのロード方法

macでdylibのプロジェクト(ここでは、libXXXX.dylib)とそれを使用するアプリ(ここではXXXXDriver)のプロジェクトがあって、xcodeからは実行できるけど、ターミナルから叩くと

dyld: Library not loaded: /usr/local/lib/libXXXX.dylib
  Referenced from: /Users/username/Library/Developer/Xcode/DerivedData/XXXXi_dylib-cagqvakmzwqigmgxxrwzutupseja/Build/Products/Release/./XXXXDriver
  Reason: image not found

Trace/BPT trap: 5

というようなメッセージが出力されて起動できない問題に対処したのでメモ

解決方法1:/usr/local/libに ロードしようとする libXXXX.dylibをコピーする

→ 環境が汚れるし、なんか負けた気がするのでNG

解決方法2:起動用のshファイルを作ってそれを叩く方法

test.shファイルを作ってそれをターミナルから叩いて実行させるようにする話。

#!/bin/sh
# dylibのロードするパスを通す
export DYLD_LIBRARY_PATH=/Users/username/Library/Developer/Xcode/DerivedData/XXXXi_dylib-cagqvakmzwqigmgxxrwzutupseja/Build/Products/Release:$DYLD_LIBRARY_PATH
# 実行
./XXXXDriver

このファイルをtest.shとして保存して、chmod +x test.sh とやって実行できるようにする。

これでターミナル上で./test.shと叩けば、きちんと実行できるようになる!!



2016年4月27日水曜日

Xamarin.FormsでiOSのネイティブコードを使用して苦労した件について

Xamarin.FormsでiOSの自作ネイティブライブラリを使用しようとしてハマった話。
普通にiOSでやれば簡単だったけど、Cross-platformにしようとしたら面倒だったという話。

環境


  • mac book pro/El Capitan
  • Xamarin 5.10.3

手順


  1. 新規ソリューションの作成でCross-platform / Xamarin.Forms Appを作る
  2. ネイティブバインディング用のプロジェクトとして、iOS / Bindings Libraryを作る
  3. Sharpieなどを使ってバインディングコードを書く
    ここあたりにやり方が描かれている。
  4. 1で作られたiOS用のプロジェクトに2のネイティブバインディングのアセンブリを参照設定で追加しようとする。
    → プロジェクト参照では、Xamarin.iOSとmonotouchで互換性がないのでNGと怒られるので、「.Net Assembly」タブの「ブラウズ」で無理くり参照設定する。
  5. ビルド
    → エラーになってビルドが通らなくなる。

対応

結局、csprojファイルを直接書き換えることで対応した。
いじる対象のcsprojファイルはバインディング側のプロジェクトファイルだ

/Project/PropertyGroup/ProjectTypeGuids要素を修正する。


    <ProjectTypeGuids>{8FFB629D-F513-41CE-95D2-7ECE97B6EEEC};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

となっている箇所を

    <ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

に変更する。
この要素は、プロジェクトのタイプを示していて、<ProjectTypeGuids>[作ったプロジェクトの種類(例えばiOSのアプリとかAndroidのアプリとか)を示す。]:[C#ということを示す。]</ProjectTypeGuids> という意味のようだ。
もともとのプロジェクトの種類が「Xamarin.iOS」だったところを、「Monotouch」へ変更する。なぜならXamarin.FormsのiOS側のプロジェクトのタイプが「Monotouch」で「Xamarin.iOS」と互換性がないからだ。

またこれに伴って、Xamarin.iOSの参照設定が使えなくなったので、参照設定で「Xamarin.iOS」を削除して、代わりに「monotouch」を追加する。
こうすることで、ネイティブバインディングプロジェクトのビルド自体は通るようになる。

次に、参照設定する側も同様にビルドをすると、エラーが発生しって相変わらずうまくいかない。
  • ネイティブバインディングから.aファイルが取り出せない。
というエラーになる。
実は本来であれば、コンパイルされたネイティブコードの.aファイルはリソースとして丸々入るのだが、今回の修正で、.aファイルはリソースに入らないという問題が発生し、そのため、参照先で.aファイルが取り出せないエラーが発生するようである。

仕方がないので、無理やりリソースに入れることとする。やり方は以下の通りだ。
  • ソリューションウインドウの、埋め込みする.aファイルで右クリックする。
  • 表示されたコンテキストメニューからビルドアクション > EmbeddedResourceを選択する。
これによって、.aファイルがリソースに含まれるようになる。

再度、参照設定する側でリビルドを行うが、今度は「MT5210」と言ったエラーが発生する。これは、ここによるとリンクしたライブラリのシンボル解決ができないということのようだ。
調べた結果、.aファイルのリソースの埋め込み名称と.aファイルをプロジェクトにドロップするときに自動生成される「〜.linkwith.cs」の中の参照先名の記述を変えてやれば良いことがわかった。

例えば、Hoge.aというネイティブライブラリをプロジェクトにドロップすると、linkwith.csでは

 [assembly: LinkWith("Hoge.a", SmartLink = true, ForceLoad = true)]

という記述が自動生成されるが、上記の「Hoge.a」という記述が生成されるアセンブリのリソース名になっていないと、参照設定する側で前述のリンクエラーが発生してしまう。
デフォルトだと、プロジェクトの名前空間名が修飾されるので、例えば「namaekuukan」というデフォルトネームスペースだったら、

 [assembly: LinkWith("namaekuukan.Hoge.a", SmartLink = true, ForceLoad = true)]

に変更する必要がある。
実際にどのようなリソース名で埋め込まれているかを調べるにはILSpyなどを使うと捗る。
この状態でソリューションビルドすることで(念のためクリーンアップしたほうが良い)、ビルドエラーが発生せずに、参照設定する側からネイティブライブラリを呼び出すことができるようになる。

なお、細かいところでは、
  • 「monotouch」に参照設定を変更したらusingしている箇所も「Monotouch.」と変更が必要になる
  • [assembly: LinkWithにリンカーフラグをつけたりする必要があったり
    →自分のところでは、「LinkerFlags = "-lstdc++"」を追記しました。
と言ったことが起きるので注意されたい。

2016年4月26日火曜日

2つのバイナリを1つに統合するけん


iOSのシミュレータ用の.aファイルと実機用の.aファイルを一つにまとめて使いやすくする巻

$> xcrun -sdk iphoneos lipo -create ../Release-iphoneos/libPDMani.a ../Release-iphonesimulator/libPDMani.a -output ../libPDMani.a

説明:

../Release-iphoneos 下の libPDMani.a (ARM系バイナリ)


../Release-iphonesimulator 下の libPDMani.a (i386系バイナリ)

を1つにまとめて-outputに指定した ../libPDMani.aに出力する方法。

-sdk iphoneos とか lipo とかはよくわからん。何かのおまじない。



2016年4月18日月曜日

Xamarinのxamlのデータバインディングのpart4について訳してみた。


Part4. データバインディングの基礎

データバインディングは2つのオブジェクトのプロパティをリンクし、片方の変更を契機に もう片方の変更を発生させることができます。 これは大変価値のあるツールです。そしてデータバインディングはソースコード上で完璧に 定義することができ、XAMLはそのショートカットと利便性を提供します。 その結果として、バインティングがXamarin.Formsのマークアップ拡張は最も重要な機能 の一つとなります。

データバインディング

データバインティングは2つのオブジェクトのプロパティを接続し、ソースからターゲットへ 呼び出しを行います。コードの中では、2つのステップが要求されます。 一つ目は、ターゲットオブジェクトのBindingContextプロパティを必ずソースオブジェクト にセットする必要があります。 二つ目は、SetBindingメソッド(しばしばBindingクラスと組み合わせて使用される)で、 ソースオブジェクトのプロパティに、そのオブジェクトのプロパティをバインドするために、 ターゲットオブジェクトから呼び出されなければなりません。
ターゲットプロパティは、バインディング可能なプロパティである必要があります。 つまり、ターゲットオブジェクトは必ずBindingObjectから継承されている必要があります。 オンラインのXamain.Formsのドキュメントでは、プロパティはバインド可能なプロパティで あることを示しています。
マークアップ中では、これらは同じ2つのステップが要求され、バインディングマークアップ の拡張機能は、SetBindingの呼び出しと、Bindingクラスの代わりに使用されます。
しかしながら、これらはターゲットオブジェクトのBindingContextへセットする単一の テクニックではありません。 しばしば、StaticResourceもしくはx:Staticマークアップ拡張機能を使用して、コード ビハインドのファイルからこれらは設定されます。
バインディングが最も頻繁に使用されるのは、画面表示系のプログラムとベースのデータモデル を接続する時で、しばしばMVVM(Model-View-ViewModel)アプリケーションアーキテクチャ で実現されます。MVVMについてはPart5で議論しますが、他のシナリオでは可能です。

ViewからViewへのバインディング

データバインディングは同一ページの二つのビューのプロパティを結合の定義をすることができます。 このケースでは、ターゲットオブジェクトのx:Refrenceマークアップ拡張を使用して、Binding - Contextを設定します。
ここにSliderと二つのラベルが含まれたの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"
             x:Class="XmalSamples.SliderBindingsPage"
             Title="Slider Bindings Page">
    <StackLayout>
        <Label Text="ROTATION"
               BindingContext="{x:Reference Name=slider}"
               Rotation="{Binding Path=Value}"
               FontAttributes="Bold"
               FontSize="Large"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

        <Slider x:Name="slider"
                Maximum="360"
                VerticalOptions="CenterAndExpand" />

        <Label BindingContext="{x:Reference slider}"
               Text="{Binding Value,
                              StringFormat='The angle is {0:F0} degrees'}"
               FontAttributes="Bold"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage>
Sliderに含まれるx:Name属性の値を使用して、二つのラベルはx:Referenceマークアップ拡張を 使用してSliderを参照します。
x:Reference拡張は、参照される要素の名前に設定するNameというプロパティを定義します。 この場合は、「slider」です。 しかしながら、ReferenceExtensionクラスはx:Referenceマークアップ拡張はまた、 明示的に要求されていないことを意味し、NameのためにContentProperty属性を定義します。
幾つかのバラエティとして、最初のラベルのx:Referenceは”Name=”が含まれていますが、 二番目のラベルには"Name="が含まれていません。
BindingContext="{x:Reference Name=slider}"
....
BindingContext="{x:Reference slider}"
Bindingマークアップ拡張自体はちょうどBindingBaseとBindingクラスのように、幾つかの プロパティを持つことができます。 バインディングのためのContentPropertyはPathですが、バインディングマークアップ拡張の 最初の項目に限り、"Path="の部分を省略することができます。 最初の例では"Path="を設定してますが、次の例ではそれを省略しています。
Rotation="{Binding Path=Value}"
...
Text="{Binding Value, StringFormat='The angle is {0:F0} degrees'}"
プロパティはすべて、単一行でも複数行に分割された行でも設定可能です。
二番目のバインディングマークアップ拡張のStingFormatに注目してください。 Xamarin.Formsでは、バインディングは暗黙の型変換を行うことができません、そして、もし 非文字列オブジェクトを文字列として表示する場合、型のコンバータ(Type Converter)か StringFormatを使用する必要があります。 バックグラウンドの動きは、StringFormatはstaticなString.Formatメソッドを使用します。 .NETの書式化の仕様も、マークアップ拡張を区切るために、XAMLパーサーを混乱させる危険性を 持っている中括弧を伴うため、潜在的な問題を持っています。 それを無効化するために、書式化文字列はシングルクォート内に設定を行います。
Text="{Binding Value,
               StringFormat='The angle is {0:F0} degrees'}"

Backwards Bindings(後方バインディング)

単一のビューは様々なプロパティのデータバインディングを行うことができます。しかしながら 各々のビューは一つのバインディングコンテキストを使用することしかできず、複数のデータを 表示用にバインディングするには、全てのオブジェクトのプロパティを参照する必要があります。
この制約を避けるには、view−to-viewバインディングを用いて、OneWayToSourceもしくは TwoWayモードをする必要があります。以下に例を挙げます。
次のプログラムは4つのスライダーがあり、スケール・回転・X軸の回転・Y軸の回転の各プロパティ の表示を意図しています。 まず、ラベルの4つのプロパティはデータバインティングのターゲットにならなければならない ことがわかります。 しかしながら、ラベルのバインディングコンテキストはただ一つのオブジェクトしか設定でき ませんが、4つの異なるスライダーが存在しています。
  • 注)データバインディングターゲット(ラベル) = 1:データソース = Nの1:Nのバインディング の話をしていると思われ。
このような理由により、バインディングは周りと一見、後方に反転しています:4つのスライダーの 各バインディングコンテキストはラベルへ設定し、バインディングはスライダーのValueプロパティ へ設定を行います。 OneWayToSourceとTwoWayモードを使用することで、これらのValueプロパティはソース プロパティで、ラベルの各プロパティ(スケール、回転、X回転、Y回転)の設定に使用します。
  • 注)ラベルへのデータバインディングをするために、スライダーへのバインディング設定 となっているということを言っている。TwoWayモードでお互いのプロパティ値の変更を 互いに変更しあうので1:Nのバインディングができるということになる。
<?xml veresion="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com//schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.SliderTransformsPage"
             Title="Slider Transforms Page">

    <Grid>
        <Grid.RowDifinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDifinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition WIdth="*" />
        </Grid.ColumnDefinitions>

        <StackLayout Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
            <!-- Scaled and rotated Lebel -->
            <Label x:Name="label"
                   Text="TEXT"
                   HorizontalOptions="Center"
                   VerticalOptions="CenterAndExpand" />
        </StackLayout>

        <!-- Slider and identifying Label for Scale -->
        <Slider x:Name="scaleSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="1" Grid.Column="1"
                Maximum="10"
                Value="{Binding Scale, Mode=TwoWay}" />
        <Label BindingContext="{x:Reference scaleSlider}"
               Text="{Binding Value, StringFormat='Scale = {0:F1}'}"
               Grid.Row="1" Grid.Column="0"
               VerticalTextAlignment="Center" />

        <!-- Slider and identifying Label for Rotation -->
        <Slider x:Name="rotationSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="2" Grid.Column="1"
                Maximum="360"
                Value="{Binding Rotation, Mode=OneWayToSource}" />
        <Label BindingContext="{x:Reference rotationSlider}"
               Text="{Binding Value, StringFormat='Rotation = {0:F0}'}"
               Grid.Row="2" Grid.Column="0"
               VerticalTextAlignment="Center" />

        <!-- Slider and identifying Label for RotationX -->
        <Slider x:Name="rotationXSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="3" Grid.Column="1"
                Maximum="360"
                Value="{Binding RotationX, Mode=OneWayToSource}" />
        <Label BindingContext="{x:Reference rotationXSlider}"
               Text="{Binding Value, StringFormat='RotationX = {0:F0}'}"
               Grid.Row="3" Grid.Column="0"
               VerticalTextAlignment="Center" />

        <!-- Slider and identifying Label for RotationY -->
        <Slider x:Name="rotationYSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="4" Grid.Column="1"
                Maximum="360"
                Value="{Binding RotationY, Mode=OneWayToSource}" />
        <Label BindingContext="{x:Reference rotationYSlider}"
               Text="{Binding Value, StringFormat='RotationY = {0:F0}'}"
               Grid.Row="4" Grid.Column="0"
               VerticalTextAlignment="Center" />

    </Grid>
</ContentPage>
3つのスライダーのバインディングはOneWayToSourceである意味は、プロパティの値の 変更が、それ自体のバインディングコンテキストによって引き起こされるためです。 これら3つのスライダーはラベルのRotate、RotateX、RotateYプロパティの変更を発生 させます。
それに対し、スケースのバインディングはTwoWayです。 これは、Scaleプロパティのデフォルトの値が1となっており、TwoWayバインディングに よってスライダーの初期値を使用することは1ではなく、0が設定されてしまうためです。
もし、バインディングがOneWayToSourceだった場合、Scaleプロパティの初期値は スライダーのデフォルト値の0となってしまいます。そうなると、ラベルは非表示となり ユーザーは混乱すると想定できるからです。
スライダーの左にあるラベルは、スライダーのカレント値を指し示しています。 これらは各ラベルが通常のOneWayでバインディングされますが、ラベルのバインティング コンテキストはスライダーを参照する必要があります。
この意味は、各スライダーは、XAMLファイルの文法的に、ラベルが表示される前に対応する ラベルが表示されている必要があることを意味しています。
このプログラムでは、Gridを使用してスライダーがカラム番号1で最初に表示され、続いて ラベルをカラム番号0として表示するように制御しています。
  • 注)ラベルの方が先に定義されると、スライダーを参照しているので、まだ出現していない オブジェクトを参照することとなり不都合があるので、XAMLの記述では、Gridの小技を 使って、スライダーの次にラベルが出現するようにしている。

バインディングとコレクション

データバインディングのパワーを示すのに、テンプレート化されたListViewに比較できる ものはありません。
ListViewはItemSourceプロパティによって列挙子の型を定義し、コレクションのアイテム を表示します。 これらのアイテムはあらゆる型のオブジェクトを扱うことができます。 既定では、ListViewはアイテムを表示するのにToStringメソッドを使用します。 大抵はこれは望む結果を生みますが、幾つかのケースではToStringメソッドはオブジェクトの 完全修飾クラス名を返します。
ListViewコレクションのアイテムは、Cellクラスから継承したクラスを含むテンプレートを 使用することによって、表示方法をコントロールすることができます。
テンプレートは、リストビュー内のすべてのアイテムのために複製され、テンプレートに設定 されているデータバインディングは、それぞれの複製されたテンプレートへ転送されます。
頻繁に、ViewCellクラスを使用してこれらのアイテムのカスタムセルを作ることを求めます。 この作業ではコードで書くと、煩雑であるが、XAMLを使うことでとても直感的に書くことが できます。
XamlSamplesプロジェクトにはNamedColorと呼ばれるクラスが含まれています。 各NamedColorオブジェクトはNameとFriendlyNameというString型のプロパティと Color型のColorプロパティを持ちます。 さらに、NamedColorは147種類のCSS3の使用に定義されたstaticなColor型のフィールド を持っています。 staticなコンストラクタで、これらstaticフィールドに対応するNamedColorオブジェクト を含むIEnumrable<NamedColor>コレクションを作成し、そのpublic-staticなすべての プロパティに割り当てます。
x;Staticマークアップ拡張を使用することでListViewのItemSourceへstaticな NamedColor.Allプロパティの設定が簡単にできます。
<?xml veresion="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:XmalSamples;assembly=XmalSamples"
             x:Class="XmalSamples.ListViewDemoPage"
             Title="ListView Demo Page">

    <ListView ItemSource="{x:Static local:NamedColor.All}" />

</ContentPage>

データバインドからMVVMへ

MVVM(Model-View-ViewModel)アーキテクチャに関する紹介

Model-View-ViewModel(MVVM)の構築パターンはXAMLを念頭に開発されました。 このパターンは ユーザーインンターフェース(View)からデータモデル(Model)を、 ビューとモデルをサービスクラスを媒介するクラス(ViewModel)を通して、両者の 分離を強制させます。
ViewとViewModelはしばしばXAMLファイルで定義されたデータバインドによって 接続されます。 Viewのバインディングコンテキストは大抵の場合、ViewModelのインスタンスと なります。

単純なViewModel

ViewModelの紹介をします。 最初にXMLの名前空間にXAMLファイルが他のアセンブリ参照の設定をどうやって行っている かを見つけることができます。 このプログラムは、アセンブリ:Systemの名前空間を修飾するXML名前空間の定義を行う プログラムがあります。
xmlns:sys="clr-namespace:System;assembly=mscorlib"
プログラムはx:Staticを使用して現在日付と時刻をstaticなDateTime.Nowプロパティ から取得して、DateTimeの値をバインディングコンテキストでStackLayoutに設定します。
<StackLayout BindingContext="{x:Static sys:DateTime.Now}" ....>
バインディングコンテキストはとても特別なプロパティで、すべてのその子供の要素に 継承されます。 この意味はStatckLayoutのすべての子供要素は同じバインディングコンテキストを持ち、 それらにオブジェクトのプロパティへの単純なバインドを含めることができます。
このプログラムでは、二つの子供要素がDateTimeのプロパティが含まれている値にバインド しており、二つの別の子供要素はバインディングパスが誤っているように見えるバインドが 行われています。 これは実際にDateTimeの値を、StringFormatのために使用されることを意味しています。
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.micosoft.com/winfx/2009/xaml"
             xmlns:sys="clr-namespace:System;assembly=mscorlib"
             x:Class="XamlSamples.OneShotDateTimePage"
             Title="One-Shot DateTime Page">
    <StackLayout BindingContext="{x:Static sys:DateTime.Now}"
                 HorizontalOptions="Center"
                 VerticalOptions="Center">

        <Label Text="{Binding Year, StringFormat='The year is {0}'}" />
        <Label Text="{Binding StringFormat='The month is {0:MMMM}'}" />
        <Label Text="{Binding Day, StringFormat='The day is {0}'}" />
        <Label Text="{Binding StringFormat='The time is {0:T}'}" />

    </StatckLayout>
もちろん、大きな問題として、日付と時間はページの初期表示に一回だけ設定されるので、 表示は更新されません。
表示結果 -> (今は2014/6/11 17:4:54)

 The year is 2014
 The month is June
 The day is 11
 The time is 5:04:54 PM
XAMLファイルは現在時刻を常に表示する時計を表示することができますが、そのためには 幾つかのヘルプコードが外部に必要となります。 MVVMの観点で考えると、モデルとモデルビューはコードで書かれたクラスになります。 ビューは大抵XAMLファイルで記述され、データバインドを通じて定義されたビューモデルの プロパティを参照します。
本来、モデルはビューモデルに依存せず、ビューモデルはビューに依存していません。 しかしながら、大抵のプログラマーは部分的なユーザーインターフェースに関連付けられた データ型をビューモデルを通じて外部に公開するような構造として作ります。
例えば、もし、モデルがデータベースの8bitキャラクターのASCII文字列にアクセスする場合、 ビューモデルはユーザーインターフェースが使用するユニコード文字列にそれらを変換する 必要があるでしょう。
この単純なMVVMの例では、モデルがなく、ビューとビューモデルが直接データバインドで接続 しています。
ビューモデルはDateTimeと名付けられた一つのプロパティを持ち、毎秒毎にDateTimeの プロパティが更新されます。
namespace XamlSamples {

class ClockViewModel : INotifyPropertyChanged
{
    DateTime dateTime;
    public event PropertyChangedEventHandler PropertyChanged = delegate {};

    public ClockViewModel()
    {
        this.DateTime = DateTime.Now;
        Device.StartTimer(TimeSpan.FromSeconds(1), () =>
        {
            this.DateTime = DateTime.Now;
            return true;
        });
    }

    public DateTime DateTime
    {
        set
        {
            if (dateTime != value)
            {
                dateTime = value;
                PropertyChanged(this,
                    new PropertyChangedEventArgs("DateTime"));
            }
        }
        get
        {
            return dateTime;
        }
    }
}

} // end of XamlSamples namespace;
ビューモデルは通常INotifyPropertyChangedインターフェースを実装します。これは プロパティの変更に伴い、PropertyChangedイベントを発火させます。 このXamarin.Formsにおけるデータバインドのメカニズムは、ProperyChangedイベントに ハンドラーを接続することで、プロパティの変更を通知することができ、ターゲットを更新して 新しい値に保つことができるようになります。
時計におけるビューモデルは以下のように単純な形で実装することができます。
<?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:XamlSamples;assembly=XamlSamples"
             x:Class="XamlSamples.ClockPage"
             Title="Clock Page">

    <Label Text="{Binding DateTime, StringFormat='{0:T}'}"
           FontSize="Large"
           HorizontalOptions="Center"
           VerticalOptions="Center">
        <Label.BindingContext>
            <local:ClockViewModel />
        </Label.BindingContext>
    </Label>
</ContentPage>
ClockViewModelがプロパティ要素のタグを使用したバインディングコンテキストへ設定を 行う方法に注目してください。 もしくは、ResourcesのコレクションでClockViewModelをインスタンス化して、StaticResource マークアップ拡張を通じたBindingContextによる設定をすることもできます。 もしくはコードビハインドファイルでViewModelをインスタンス化することもできます。
ラベルのTextプロパティにバインディングしたマークアップ拡張はDateTimeを書式化して 表示します。 以下のように表示されるでしょう。

5:05:16 PM

これもまた、期間が分離されたViewModelのDateTimeプロパティの個別のプロパティに アクセスすることができます。
<Label Text="{Binding DateTime.Second
                      StringFormat='{0}'}" .... >

インタラクティブなMVVM

MVVMはデータモデルをベースとしたインタラクティブな表示のためにtwo-wayなデータバインド しばしば使用します。 これは、HslViewModelと名づけられた色相、彩度、明度の値とColorを相互変換するクラスが あります。

public class HslViewModel : INotifyPropertyChanged
{
    double hue, saturation, luminosity;
    Color color;

    public event PropertyChangedEventHandler ProperyChanged;

    public double Hue
    {
        set
        {
            if (hue != value)
            {
                hue = value;
                OnPropertyChanged("Hue");
                SetNewColor();
            }
        }
        get { return hue; }
    }

    public double Saturation
    {
        set
        {
            if (saturation != value)
            {
                hue = value;
                OnPropertyChanged("Saturation");
                SetNewColor();
            }
        }
        get { return Saturation; }
    }

    public double Luminosity
    {
        set
        {
            if (luminosity != value)
            {
                hue = value;
                OnPropertyChanged("Luminosity");
                SetNewColor();
            }
        }
        get { return Luminosity; }
    }

    public Color Color
    {
        set
        {
            if (color != value)
            {
                color = value;
                OnPropertyChanged("Color");

                this.Hue = value.Hue;
                this.Saturation = value.Saturation;
                this.Luminosity = value.Luminosity;
            }
        }
        get { return color; }
    }

    void SetNewColor()
    {
        this.Color = Color.FromHsla(this.Hue, this.Saturation, this.Luminosity);
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (ProperyChanged != null)
        {
            ProperyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
色相、彩度、明度の各プロパティに変更が発生した場合、Colorプロパティが変更されColorの 変更は他の3つのプロパティへの変更を発生させます。 これはプロパティが実際に変更されていない限り、PropertyChangedイベントが発火されない ことを除いて、無限ループのように見えるかもしれません。 さもなければ制御不能なフィードバックのループに終止符を打ちます。
XAMLファイルに含まれたBoxViewは、ColorプロパティをViewModelのColorプロパティと 接着させて、3つのスライダーと3つのラベルに色相・彩度・明度プロパティを接着させます。
<?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:XamlSamples;assembly=XamlSamples"
             x:Class="XamlSamples.HslColorScrollPage"
             Title="HSL Color Scroll Page">

    <ContentPage.BindingContext>
        <local:HslViewModel Color="Aqua"/>
    </ContentPage.BindingContext>

    <StackLayout Padding="10, 0">
        <BoxView Color="{Binding Color}"
                 VerticalOptions="FillAndExpand" />
        <Label Text="{Binding Hue, StringFormat='Hue = {0:F2}'}"
               HorizontalOptions="Center" >
        <Slider Value="{Binding Hue, Mode=TwoWay}" />

        <Label Text="{Binding Saturation, StringFormat='Saturation = {0:F2}'}"
               HorizontalOptions="Center" >
        <Slider Value="{Binding Saturation, Mode=TwoWay}" />

        <Label Text="{Binding Luminosity, StringFormat='Luminosity = {0:F2}'}"
               HorizontalOptions="Center" >
        <Slider Value="{Binding Luminosity, Mode=TwoWay}" />
    </StackLayout>


</ContentPage>
各ラベルへのデフォルトのバインド方法はOneWayです。これは値を表示するのみが必要な時に 限られます。しかし、各スライダーはTwoWayでバインドされます。 この方法はViewModelによってスライダーが初期化される良い方法です。 ColorプロパティはViewModelがインスタンス化されるタイミングで青に設定される一方で、 スライダーの変化も、ViewModelで新しい色の値を算出し、プロパティに設定する必要が あることに注目してください。