本日のサンプルコードは後日公開します
作業手順も暗記する必要はありません
-クロスデバイス開発の必要性
iOS
Android
WinRT
Objective-C Storyboard Java AXML C#/VB XAML
iOS ライブラリ Android ライブラリ .NET BCL iOS Native API Android Native API WinRT Native API
異なる
言語 異なる
-Xamarin & Xamarin.Forms による解決
iOS
Android
WinRT
C# Storyboard C# AXML C#/VB XAML
Xamarin.Forms
Portable Class Library
(または Shared Asset Project)
C# で 記述可能! C# XAML 共有 可能! 共有 可能!
-Xamarin.Forms の向き・不向き
Xamarin.Forms が得意なアプリ Xamarin.Forms が苦手なアプリ • アニメーションを多用 • 複雑な UI 操作が必要 • プラットフォーム固有処 理が大量に必要 • 比較的シンプルな UI • データ参照・更新が主体 • プラットフォーム固有処 理が比較的少ない-具体例)データバインドアプリケーション
iPhone 6 (実機) Nexus 7 2013 (実機) iPad 2 (実機)シングルコード
マルチデバイス
-Hello World, Xamarin.Forms !
PCL タイプの Xamarin.Forms プロ ジェクトを作成 ※ 手作業でソリューションファイ ルを組み立てることも可能 業務構造を意識した 形で XAML ファイル を追加 ブートストラップコードが 含まれるプロジェクト Xamarin.Forms を利用する 共有 PCL プロジェクト
-Hello World, Xamarin.Forms !
HelloWorldPage.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="Decode2015.MainPage" Title="メインメニュー"> <StackLayout>
<Button x:Name="btnBizA" Text="Hello World サンプル" /> </StackLayout> </ContentPage> <?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="Decode2015.BizA.HelloWorldPage" Title="Hello World"> <StackLayout>
<Entry x:Name="entName" Text="Nobuyuki" />
<Button x:Name="btnGetMessage" Text="メッセージ取得" /> <Label x:Name="lblMessage" />
</StackLayout>
</ContentPage>
-Hello World, Xamarin.Forms !
public HelloWorldPage() {
InitializeComponent();
btnGetMessage.Clicked += btnGetMessage_Clicked; }
void btnGetMessage_Clicked(object sender, EventArgs e) {
lblMessage.Text = "Hello World, " + entName.Text; } HelloWorldPage.xaml.cs public MainPage() { InitializeComponent(); btnBizA.Clicked += btnBizA_Clicked; }
void btnBizA_Clicked(object sender, EventArgs e) {
Navigation.PushAsync(new BizA.HelloWorldPage()); }
-Hello World, Xamarin.Forms !
public class App : Application {
public App() {
this.MainPage = new NavigationPage(new MainPage()); } } C# NavigationPage でペー ジをラップすると... ヘッダーが付与されるよ うになり、iOS でも前画 面に戻れるようになる
-Hello World, Xamarin.Forms !
開発機 Macintosh
Xamarin.iOS
Build Host iOS シミュレータ
Visual Studio iOS 実機
配置と実行 Android 実機
Android エミュレータ 仮想化環境
-デバイスによる実行結果の差異について
XAML <Label> <Label.Text> <OnPlatform x:TypeArguments="x:String" iOS="Hello World, iOS"Android="Hello World, Android"
WinPhone="Hello World, WinPhone" />
</Label.Text> </Label>
// 値を変えたい場合
lblMessage.Text = Device.OnPlatform<string>( "iOS", "Android", "WinPhone"); // 処理を分けたい場合 Device.OnPlatform( () => { lblMessage.Text = "iOS"; }, () => { lblMessage.Text = "Android"; }, () => { lblMessage.Text = "WinPhone"; } ); C# ① OnPlatform 属性の利用 ② Device.OnPlatform メソッドの利用
-WinRT XAML と Xamarin.Forms XAML の類似点と相違点
【主な類似点】
• XAML の基本的な構文
• リソースデータの扱い
• スタイルの考え方
• データバインドの考え方
• 主要なレイアウト部品や
UI 部品
【主な相違点】
• UI 部品やレイアウト部品
の名前
• 主要プロパティの名前
• 任意のコンテンツ合成や高
度な UI 指定ができない
-Xamarin.Forms アプリからのサーバ連携
Web サーバ
DB サーバ
各種の
既存の
各システム
XML 形式 などのデータ 業務データXamarin.Forms
アプリケーション
開発!
-PCL におけるサービス参照について
• PCL プロジェクトでもサービス
参照の機能は利用できるように
見えるが...
• 実際に作成してみると、Android,
iOS では残念ながら動作しない
-スクラッチでのリモート通信開発
Web サーバ
業務データDB サーバ
クライアント
ツールベースの開発
通信手法
サービス参照
(プロキシクラス)
SOAP
(または *.asmx)
WCF
スクラッチでの開発
HttpClient
XML または
JSON
ASP.NET Web API
こちらを
利用!
-HttpClient + Web API + EF によるサーバアプリ開発
Web サーバ
pubs データベースXamarin.Forms
アプリケーション
データ転送
オブジェクト
(AuthorDTO)
Web API コントローラ
(ListAuthors
WebApiController)
O/R マッパー
(Pubs.dbml)
(ListAuthorsPage.xaml)
HttpClient
-HttpClient + Web API + EF によるサーバアプリ開発
• データ転送用の POCO (DTO) を別 建てで PCL として定義 • サーバとクライアントの両方から参照 設定して共有する Web サーバ 業務データ DB サーバ クライアント データ転送オブジェクト iOS Android Xamarin .Forms DTO ASP.NET Web API 参照! 参照!
-HttpClient + Web API + EF によるサーバアプリ開発
開発機
Macintosh
Xamarin.iOS Build Host シミュレータ Visual Studio 実機 配置と実行 IIS Express エミュレータ 実機 仮想化環境 開発用 Web サーバ エミュレータ/シミュレータ /実機いずれからもアクセ スできない! Azure Web サイト 開発用 Web サーバや Azure Web サイトを使い、 開発とテストを行う
-HttpClient + Web API + EF によるサーバアプリ開発
public MainPage() { InitializeComponent(); btnBizA.Clicked += btnBizA_Clicked; btnBizB.Clicked += btnBizB_Clicked; }
void btnBizB_Clicked(object sender, EventArgs e) { Navigation.PushAsync(new BizB.ListAuthorsPage()); } C# <?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="Decode2015.MainPage" Title="メインメニュー"> <StackLayout>
<Button x:Name="btnBizA" Text="Hello World サンプル" />
<Button x:Name="btnBizB" Text="著者データ参照" />
</StackLayout> </ContentPage>
-HttpClient + Web API + EF によるサーバアプリ開発
[DataContract]
public class AuthorDTO {
[DataMember]
public string AuthorId { get; set; } [DataMember]
public string AuthorName { get; set; } }
-HttpClient + Web API + EF によるサーバアプリ開発
[Route("BizB/ListAuthors/{action}")]
public class ListAuthorsWebApiController : ApiController {
[HttpGet]
public List<AuthorDTO> GetAllAuthors() { ... (完全なソースコードは次ページ参照) } } C#
重要!
[Route("BizB/ListAuthors/{action}")]
public class ListAuthorsWebApiController : ApiController {
[HttpGet]
public List<AuthorDTO> GetAllAuthors() {
using (pubsEntities pubs = new pubsEntities()) {
var query = from a in pubs.authors select new AuthorDTO
{
AuthorId = a.au_id,
AuthorName = a.au_fname + " " + a.au_lname }; return query.ToList(); } } } C#
-HttpClient + Web API + EF によるサーバアプリ開発
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="Decode2015.BizB.ListAuthorsPage" Title="著者データ参照">
<StackLayout>
<ListView x:Name="lvwAuthors" RowHeight="60" VerticalOptions="FillAndExpand"> <ListView.ItemTemplate>
<DataTemplate> <ViewCell>
<ViewCell.View>
<StackLayout Orientation="Vertical" Padding="0,6,0,0">
<Label Text="{Binding AuthorId}" FontAttributes="Bold" FontSize="18" />
<Label Text="{Binding AuthorName}" FontSize="18" LineBreakMode="TailTruncation" /> </StackLayout> </ViewCell.View> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView>
<Button x:Name="btnGetAllAuthors" Text="データ取得" /> </StackLayout>
-HttpClient + Web API + EF によるサーバアプリ開発
public ListAuthorsPage() {
InitializeComponent();
btnGetAllAuthors.Clicked += btnGetAllAuthors_Clicked; }
async void btnGetAllAuthors_Clicked(object sender, EventArgs e) {
string apiUrl = "http://decode2015webapi.azurewebsites.net/BizB/ListAuthors/GetAllAuthors";
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.GetAsync(apiUrl);
string responseString = await response.Content.ReadAsStringAsync();
List<AuthorDTO> results = JsonDeserialize<List<AuthorDTO>>(responseString); lvwAuthors.ItemsSource = results;
}
-HttpClient + Web API + EF によるサーバアプリ開発
public static T JsonDeserialize<T>(string stringToDeserialize) {
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T)); byte[] bytes = Encoding.UTF8.GetBytes(stringToDeserialize);
MemoryStream ms = new MemoryStream(bytes); return (T)serializer.ReadObject(ms);
}
-アプリケーションアーキテクチャ上のポイント
-1. RESTful 型設計 vs RPC 型設計
商品発注サービス カタログ管理サービス 注文伝票 注文結果伝票 サービス 呼び出し商品
口コミ
GET PUT DELETE GET PUT DELETE CRUD 処理 RESTful 設計 RPC スタイル設計業務アプリではこちらの方が設計しやすい
-1. RESTful 型設計 vs RPC 型設計
public class AuthorsController : ApiController
{
public List<Author> Get() { ... }
public Author Get(string authorId) { ... }
public void Put(Author authorToUpdate) { ... }
public void Post(Author authorToInsert) { ... }
public void Delete(string authorId) { ... }
}
C#HTTP Verb 意味
GET
READ
POST
CREATE
PUT
UPDATE
DELETE
DELETE
-1. RESTful 型設計 vs RPC 型設計
-2. JSON vs XML
{"result":"Hello World
Nobuyuki"}
簡単なデータならよいが、 日付型や byte[] 型などの 扱いは面倒
-2. JSON vs XML
string apiUrl = "http://decode2015webapi.azurewebsites.net/BizB/ListAuthors/GetAllAuthors";
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("text/xml"));
HttpResponseMessage response = await httpClient.GetAsync(apiUrl);
string responseString = await response.Content.ReadAsStringAsync();
-WCF vs ASP.NET Web API
WCF
ASP.NET Web API
API 設計スタイル
RPC 型のみ
自由
(RPC 型、RESTful 型など)
メッセージフォー
マット
SOAP のみ
自由
(XML、JSON など)
通信プロトコル
自由
-WCF vs ASP.NET Web API
Web サーバ
業務データDB サーバ
クライアント
ツールベースの開発
通信手法
サービス参照
(プロキシクラス)
SOAP
(または *.asmx)
WCF
スクラッチでの開発
HttpClient
XML または
JSON
ASP.NET Web API
要
設計
本日のランチセッションにて開催!
1. WinRT と Xamarin.Forms XAML の主な相違点
2. ASP.NET Web API + EF の開発テクニック
-レイアウト部品の名称の違い
Xamarin.Forms
WinRT
積み重ね
StackLayout
StackPanel
絶対座標
AbsoluteLayout
Canvas
格子状
GridLayout
Grid
相対座標
RelativeLayout
(なし)
スクロール
ScrollView
ScrollViewer
枠線
Frame
Border
サイズフィット
(なし)
Viewbox
-StackLayout の活用テクニック
Xamarin.Forms XAML <ContentPage ...> <StackLayout><Frame OutlineColor="Accent"> ... </Frame>
<ScrollView Orientation="Vertical" VerticalOptions="FillAndExpand"> <StackLayout>
... (表示する内容) ... </StackLayout>
</ScrollView>
<Button x:Name="btnUpdate" Text="更新" BorderWidth="2" />
<Button x:Name="btnGoBack" Text="前の画面に戻る" BorderWidth="2" />
</StackLayout>
</ContentPage>
FillAndExpand
余白いっぱいに 引き伸ばす
-UI 部品の名前の違い
Xamarin.Forms
WinRT の場合は...
ActivityIndicator
ProgressRing
BoxView
Rectangle
Button
Button
DatePicker
DatePicker
Editor
TextBox
Entry
TextBox
Image
Image
Label
TextBlock
ListView
ListView
Xamarin.Forms
WinRT の場合は...
Map
BingMaps
Picker
ComboBox
ProgressBar
ProgressBar
Slider
Slider
Switch
ToggleButton
TimePicker
TimePicker
WebView
WebView
-
CheckBox
-
GridView
-主要プロパティの名前の違い
WinRT Xamarin.Forms 余白制御 Margin Padding 位置制御 VerticalAlignment/HorizontalAlignment VerticalOptions/HorizontalOptions 前景色 Foreground TextColor など 背景色 Background BackgroundColor/BackgroundImage など データバインド DataContext BindingContext
-
データアノテーションを利用した単体入力エラーチェック
[DataContract]
public class FindAuthorRequestDTO {
[DataMember] [Required]
[RegularExpression(@"^[0-9]{3}-[0-9]{2}-[0-9]{4}$")]
public string AuthorId { get; set; } } C# [HttpPost] public AuthorDetailDTO FindAuthor(FindAuthorRequestDTO request) {
if (ModelState.IsValid == false) throw new
HttpResponseException(HttpStatusCode.BadRe quest);
.... }
-
EF エンティティデータモデルのシリアル化
-
EF エンティティデータモデルのシリアル化
public string Property(EdmProperty edmProperty) {
return string.Format(...,
"[System.Runtime.Serialization.DataMember]¥r¥n{0} {1} {2} {{ {3}get; {4}set; }}", ...);
}
public string NavigationProperty(NavigationProperty navProp) {
...
return string.Format( ..,
"[System.Runtime.Serialization.DataMember]¥r¥n{0} {1} {2} {{ {3}get; {4}set; }}", ...); }
public string EntityClassOpening(EntityType entity) {
return string.Format(...,
"[System.Runtime.Serialization.DataContract(IsReference = true)]¥r¥n {0} {1}partial class {2}{3}", ...); }
Pubs.tt
i.
ii.
-
3 種類の POCO オブジェクトの使い分け
DAC データベース *.edmx SI + BCASP.NET Web API API Controller POCO (エンティティ) BEC ADO.NET Entity Framework POCO (DTO) BEC SA HttpClient BC サーバ呼び出し ロジック Xamarin .Forms *.xaml *.xaml.cs コードビハインド POCO (ViewModel) UI