rksoftware

Visual Studio とか C# とかが好きです

Xamarin で PApiHelper を使ってみる

以前に「プリザンターの API を扱う .NET ライブラリを書いてみた」記事を書きました。

今回は、このライブラリを Xamarin.Forms アプリで使ってみます。

■ 完成イメージ

一覧ページ

テーブルの ID を入力して [ 検索 ] ボタンでテーブルのデータをリスト表示します。
f:id:rksoftware:20181213013106j:plain
テーブルの ID を直接入力するスタイルでは少々アプリとして使い勝手は良くないかもしれませんが、テーブルを検索する API がないので今はこれが限界です。

詳細ページ

リストのタップで詳細を表示します。
f:id:rksoftware:20181213013127j:plain
API で取ってきた値を表示しているだけです。状況や管理者、担当者を表示していますが API で取ってくる値が名前でなくコード値なので若干アプリとしての使い勝手に難があるかもしれませんが、今はこれが限界です。
管理者、担当者は別途一覧で取得できる API があるので組み合せれば何とかなりそうですが、独自に作った選択肢項目などは頑張っても API 現状の API だけでは取れません。

■ ソリューションの作成

ソリューションは普通に Xamarin.Forms の空白ページのテンプレートで作成します。
今回は名前を PApiClient で作成しました。

■ NuGet の管理

今回のメイン。NuGet で PApiHelper を検索してすべてのプロジェクトにインストールします。
f:id:rksoftware:20181213013325j:plain

■ コード(App.xaml.cs)

まずは複数ページアプリにするいつもの手順です。 App.xaml.cs で MainPage に NavigationPage を設定します。

MainPage = new NavigationPage(new MainPage());

ファイル全体では次のようになります。

using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace PApiClient
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();

            MainPage = new NavigationPage(new MainPage());
        }

        protected override void OnStart()
        {
            // Handle when your app starts
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}

■ 一覧ページ(MainPage.xaml/MainPage.xaml.cs)

一覧表示の画面です。プロジェクト新規作成時に作成された MainPage を書き換えて行きます。
UI には普通に ID を入力する Entry、API を叩く Button、一覧表示する ListView を並べています。

<?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:PApiClient"
             x:Class="PApiClient.MainPage">
    <StackLayout>
        <Label Text="ID:" HorizontalOptions="Start"/>
        <Entry x:Name="idEntry"/>
        <Button Text="検索" Clicked="Button_Clicked"/>
        <ListView HorizontalOptions="Fill" VerticalOptions="Fill"
                  x:Name="listView" ItemSelected="ListView_ItemSelected">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Horizontal">
                            <Label Text="{Binding ResultId}"/>
                            <Label Text="{Binding ItemTitle}"/>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

今回はサンプルコードを少なくするためにコードビハインドに書いています。
Button の Clicked で普通に API を叩いています。 注意点としては、ホストのアドレスと APIKey の設定があります。

ホストのアドレス

今回のテーマでの開発の場合、通常は Windows 10 Pro 環境を使っていると思います。その場合、Web のプロジェクトは IIS Express ではなく、ローカル IIS で実行する必要があります。アプリから Web へのアクセスは localhost ではなく、PC のアドレスを指定します(Android のエミュレーターの場合でも、ホストを指す 10.0.2.2 ではつながりません)。
mac と iOS シミュレーターの組み合わせの場合は、localhost でも行けるかもしれませんが、今回は Web が mac で動作しないため考える必要がありません。

ローカル IIS で実行する手順は別の記事に書いているので、準備の整っていない方は参考にしてください。

APIKey の取得

APIKey はメニューの [ API 設定 ] から取得します。APIKey は誤って公開しても何度でも [ 再作成 ] できるので恐れず GitHub を使って行きましょう。
f:id:rksoftware:20181213013355j:plain f:id:rksoftware:20181213013409j:plain

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace PApiClient
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        // 検索ボタン
        private async void Button_Clicked(object sender, EventArgs e)
        {
            // 取得する ID
            long.TryParse(idEntry.Text, out var id);

            // Api クライアント準備
            var helper = new PApiHelper.PApiClient()
            {
                BaseUrl = "http://<ホストのアドレス>/Implem.Pleasanter",
                ApiKey = "<あなたのAPIKey>"
            };

            // 取得
            var items = await helper.PostGetItemsAsync(id, new PApiHelper.Models.PGetApiRequest());

            // View に表示
            listView.ItemsSource = items.Response.Data;
        }

        // リスト選択
        private async void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            var item = e.SelectedItem as PApiHelper.Models.DataModels.PApiItem;
            if (item == null) return;
            await Navigation.PushAsync(new DetailPage(item));
            listView.SelectedItem = null;
        }
    }
}

■ 詳細ページ(DetailPage.xaml/DetailPage.xaml.cs)

詳細ページは単純にデータを表示しているだけです。特に見どころはありません。
現時点での API では、テーブルの構成(どのようなカラムが使われているか等)を取得できないので、固定で項目を選別しています。
選択項目の値もコード値になっていて、いわゆる名前解決はできていません。
このあたりの解決には API の独自追加が必要になると思います。

<?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="PApiClient.DetailPage">
    <ContentPage.Content>
        <StackLayout>
            <Label Text="{Binding ResultId}"/>
            <Label Text="{Binding ItemTitle}"/>
            <Label Text="{Binding Status}"/>
            <Label Text="{Binding Manager}"/>
            <Label Text="{Binding Owner}"/>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace PApiClient
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class DetailPage : ContentPage
    {
        PApiHelper.Models.DataModels.PApiItem _item { get; }

        public DetailPage (PApiHelper.Models.DataModels.PApiItem item)
        {
            _item = item;
            InitializeComponent ();
            this.BindingContext = item;
        }
    }
}

■ 実行

これで、Xamarin.Froms で API をたたくシンプルなサンプルができました。
f:id:rksoftware:20181213013127j:plain
f:id:rksoftware:20181213013127j:plain