nuits.jp blog

C#, Xamarin, WPFを中心に書いています。Microsoft MVP for Development Technologies。

Hello, Azure API Apps with Xamarin.Forms

前回、Azure API Appの簡単な利用方法を解説しました。

www.nuits.jp

今回は、これをXamarin.Formsから利用してみましょう。

Xamarinプロジェクトを作成する

まず、前回作成したソリューションにXamarin.Formsのプロジェクトを追加します。
ここでは「HelloXamarin」という名称にしました。

f:id:nuitsjp:20170712113614p:plain

さて、前回作成したRESTクライアントはMicrosoft.Rest.Clientを利用していますが、これは.NET Frameworkか.NET Standard 1.4以上しかサポートしていません。

f:id:nuitsjp:20170712113801p:plain

PCLのプロジェクトは、プロファイルによって利用できる.NET Standardのバージョンが異なりますが、どうがんばっても1.2止まりです。

f:id:nuitsjp:20170712114001p:plain

https://docs.microsoft.com/en-us/dotnet/standard/net-standard

このため、PCLは諦めてXamarin.Formsの共通プロジェクトを.NET Standard化します。

という訳で、まずはHelloXamarinプロジェクトを削除します。

f:id:nuitsjp:20170712114204p:plain

プロジェクトから削除しても、ファイルシステムには残っています。
後から、AppクラスとMainPageクラスは再利用したいので、ここではフォルダは削除せず「HelloXamarinOriginal」にフォルダ名を変更しています。

f:id:nuitsjp:20170712114354p:plain

つづいて、.NET Standardのクラスライブラリを「HelloXamarin」という名称で作成します。

f:id:nuitsjp:20170712114619p:plain

注意点が一つあります。
「HelloXamarin」という名称のXamarin.Formsのソリューションフォルダが存在しますので、「HelloXamarin」という名称の.NET Standardクラスライブラリを作成するときは、作成場所に注意しましょう。ソリューションフォルダの下に作成すれば良いかと思います。

さて、作成した.NET StandardプロジェクトからNuGetを通してXamarin.Formsを追加したいところですが、現時点ではXamarin.FormsはPCLなのでそのままでは追加できません。
そこでcsprojを直接編集して、PCLを参照可能にし、ついでにXamarin.Formsの参照をつけてしまいましょう。

プロジェクトを右クリックし「HelloXamarin.csprojを編集する」をクリックしてください。

f:id:nuitsjp:20170712115050p:plain

そして次のように書き換えてしまいましょう。

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard1.4</TargetFramework>
    <PackageTargetFallback>portable-net45+win8+wpa81+wp8</PackageTargetFallback>
    <DebugType>full</DebugType>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Rest.ClientRuntime" Version="2.3.8" />
    <PackageReference Include="Xamarin.Forms" Version="2.3.4.247" />
    <PackageReference Include="Xamarin.Forms.BehaviorsPack" Version="1.2.0" />
  </ItemGroup>
  <ItemGroup>
    <!-- https://bugzilla.xamarin.com/show_bug.cgi?id=55591 -->
    <None Remove="**\*.xaml" />
    <Compile Update="**\*.xaml.cs" DependentUpon="%(Filename)" />
    <EmbeddedResource Include="**\*.xaml" SubType="Designer" Generator="MSBuild:UpdateDesignTimeXaml" />
  </ItemGroup>
</Project>

PackageTargetFallbackという要素が指定されていますが、これは利用したいNuGetパッケージに対象の.NET Standardのパッケージがなかった場合は、強制的に指定プロファイルのPCLのライブラリを使ってね、と指定していることになります。
つまりXamarin.FormsのPCLのバイナリをこれを通して参照させています。
また、今回はUWPも対象にしているため、.NET Standardは1.4にしています。

なおXamarin.Formsの.NET Standard化については、次のブログも参考になりますので一読する事をお勧めします。

medium.com

さて、よく見ると参照しているパッケージが3つありますね。

  1. Microsoft.Rest.ClientRuntime
  2. Xamarin.Forms
  3. Xamarin.Forms.BehaviorsPack

1.と2.は説明は不要でしょう。3.ですが、後でサンプルコードを書くのを楽するために利用します。
利用頻度の高い汎用的なBehaviorライブラリで超お勧めです。特に作者がいい感じです。

www.nuget.org

さて、それでは「HelloXamarinOriginal」に名前変更しておいたフォルダから、AppクラスとMainPageクラスをコピってきましょう。xamlとxaml.csがあるので4ファイルある事を忘れないでください。
これを

f:id:nuitsjp:20170712120058p:plain

こう、コピッペッとします。

f:id:nuitsjp:20170712120152p:plain

あとは、Android・iOS・UWPプロジェクトから参照を再設定すれば完了です。
ここまででひとまずビルドして実行できることを確認しましょう。

XamarinにAPI App呼び出しを組み込む

つぎのような手順で組み込んでいきます。

  1. MainPageViewModelの「ガワ」を作る
  2. MainPage.xamlをつぎの三つの観点で修正する
    1. MainPageViewModelをBindingContextへバインド
    2. API Appを呼び出すコマンドを実行するBehaviorの追加
    3. API Appの呼び出し結果の表示
  3. APIクライアントの組込み

MainPageViewModelの作成

MainPageViewModel.csを追加し、ひとまず次のようなコードを書きましょう。
まだ「ガワ」だけで肝心のAPIの呼び出し処理はありません。

public class MainPageViewModel
{
    public ObservableCollection<string> Values { get; } = new ObservableCollection<string>();

    public Command GetAllCommand { get; }

    public MainPageViewModel()
    {
        GetAllCommand = new Command(GetAll);
    }

    private async void GetAll()
    {
    }
}

つぎの三つが存在する事が見て取れるでしょう。

  • API Appを実際に呼び出す想定のGetAllメソッド(まだ空っぽ)
  • GetAllメソッドを呼び出すGetAllCommand
  • API Appの呼び出し結果を格納する想定のObservableCollection Values

MainPage.xamlの修正

先にも説明した通り、つぎの三点を組み込みます。

  1. MainPageViewModelをBindingContextへバインド
  2. API Appを呼び出すコマンドを実行するBehaviorの追加
  3. API Appの呼び出し結果の表示
<?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:HelloXamarin"
             xmlns:behaviorsPack="clr-namespace:Xamarin.Forms.BehaviorsPack;assembly=Xamarin.Forms.BehaviorsPack"
             x:Class="HelloXamarin.MainPage">
    <ContentPage.BindingContext>
        <local:MainPageViewModel/>
    </ContentPage.BindingContext>
    <ContentPage.Behaviors>
        <behaviorsPack:EventToCommandBehavior EventName="Appearing" Command="{Binding GetAllCommand}"/>
    </ContentPage.Behaviors>
    <Grid>
        <ListView ItemsSource="{Binding Values}"/>
    </Grid>
</ContentPage>

BindingContextにMainPageViewModelが設定されており、API Appの戻り値をListViewに設定しようとしているのが見て取れるでしょう。
ポイントはEventToCommandBehaviorです。

<behaviorsPack:EventToCommandBehavior EventName="Appearing" Command="{Binding GetAllCommand}"/>

良くあるBehaviorですが、PageのAppearingイベントが発行された時(つまり画面の初期表示時など)にGetAllCommandを呼び出すよう定義しています。
こういった、利用頻度が高いBehaviorがいくつかセットになっているので、Xamarin.Forms.BehaviorsPackお勧めです。作者的に。

APIクライアントの組込み

それではいよいよAPIクライアントを組み込んでいきましょう。
まずは前回のエントリーで作成したつぎの四つのクラスをコピーします。

  1. AnonymousServiceClientCredentials.cs
  2. HelloApiService.cs
  3. HelloApiServiceExtensions.cs
  4. IHelloApiService.cs

こんな感じですね。

f:id:nuitsjp:20170712130020p:plain

そしてMainPageViewModelにクライアントを呼び出す処理を実装しましょう。
実装する先はGetAllメソッドです。

private async void GetAll()
{
    var helloApiService =
        new HelloApiService(
            new Uri("http://helloapiservice.azurewebsites.net"),
            new AnonymousServiceClientCredentials());
    var values = await helloApiService.GetAllAsync();
    foreach (var value in values)
    {
        Values.Add(value);
    }
}

さあ動かしてみよう!

ということで、Androidエミュレーターで実行したのが次のイメージです。

f:id:nuitsjp:20170712130232p:plain

これでAzure API ServiceとXamarin(他クライアント)を連携させる基本が実現できました。
もっと簡単な方法があるかも知れませんが、ご存知の方は良かったら教えていただけると嬉しいです。

では今回はここまで。
それではまた!