はまったりひらめいたり…とか…

Angularや.NETやAzureやその他色々。

Angular2 + VisualStudio(ASP.NET MVC"4") + VisualBasic.net

風邪ひいてたりなんだりで全然ブログ更新してませんでしたー。っと。

Angular2とASP.NET MVC"4"をお仕事でいじることになりました。

Angular2 + VisualStudio(ASP.NET MVC"4") + VisualBasic.net

ニッチすぎて参考文献が少なく、VS上で動かすまでに色々と面倒くさかったのでメモ残します。

使用環境

  • VisualStudio2015(Update2)
  • TypeScript(1.8.29.0)

環境構築

1.ひとまずプロジェクトを作成

f:id:TakasDev:20160609221724p:plain
業務の都合上VB.netでプロジェクト作成していますが

今回記述ソースは.net側は、ほとんど何もありません。

VB.netなのでMVC5はテンプレート上存在しないので、MVC4を選択しました。

2.npmのpackage.jsonファイルを追加

rootにpackage.jsonを追加します。

記述するソースは下記のとおり。

{
  "name": "angular2-quickstart",
  "version": "1.0.0",
  "scripts": {
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "lite": "lite-server",
    "start": "concurrent \"npm run tsc:w\" \"npm run lite\" "
  },
   "license": "ISC",
  "dependencies": {
    "angular2": "2.0.0-beta.1",
    "systemjs": "0.19.6",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.33.3",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.0",
    "zone.js": "0.5.10"
  },
  "devDependencies": {
    "concurrently": "^1.0.0",
    "lite-server": "^1.3.2",
    "typescript": "^1.7.5" 
  }
} 

4.パッケージインストール

f:id:TakasDev:20160609222757p:plain

5.Rootディレクトリにtsconfig.jsonを作成

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "outDir": "app/"
  },
  "exclude": [
    "node_modules"
  ]
}

outDirに.tsファイルから生成した.jsファイルが出力されます。

6.BundleConfigにAngular2読み込みを追加

        bundles.Add(New ScriptBundle("~/bundles/angular2").Include(
            "~/node_modules/es6-shim/es6-shim.js",
            "~/node_modules/systemjs/dist/system-polyfills.js",
            "~/node_modules/angular2/bundles/angular2-polyfills.js",
            "~/node_modules/systemjs/dist/system.src.js",
            "~/node_modules/rxjs/bundles/rx.js",
            "~/node_modules/angular2/bundles/angular2.dev.js",
            "~/node_modules/angular2/bundles/router.dev.js",
            "~/node_modules/angular2/bundles/http.dev.js"
            ))

7.app.tsを作成

scriptsディレクトリにappディレクトリを作成。
appディレクトリにapp.tsファイルを作成。

import {Component} from 'angular2/core';
@Component({
    selector: 'my-app',
    template: '<h1>Angular 2 Sample Application</h1>'
})
export class AppComponent { }

8.エラー発生

app.tsに下記のエラーが発生
f:id:TakasDev:20160609224013p:plain

まずひとつ。TypeScript古いですよー。ってメッセージが出る。

これ、Resharperが入っている場合にでるエラーだそう。

ReSharperの設定をいじることで解決。

参考:
stackoverflow.com


残りのエラー
f:id:TakasDev:20160609224205p:plain

これは、promise.d.tsに

declare var Promise: PromiseConstructor;

を加えることで解決できるらしい。

参考:
github.com

最後 _Layout.vbhtmlを改造

HEADに下記

    @Scripts.Render("~/bundles/angular2")
    <script>
      System.config({
        transpiler: 'typescript',
        typescriptOptions: { emitDecoratorMetadata: true },
        packages: {'app': {defaultExtension: 'js'}}
      });
      System.import('app/boot')
            .then(null, console.error.bind(console));
    </script>

BODYに下記を記述

<my-app>Loading...</my-app>

結果

f:id:TakasDev:20160609224654p:plain
表示できました。

f:id:TakasDev:20160609225634p:plain
最終出力時点のディレクトリ構成は上図のとおりです。

というわけで、Angular2の開発実験場が整ったわけです。

長かった…。

Xamarinやろーっと。

Xamarin.FormsのGridについて

下図の画面をGridで作成するための前準備のお話し。

Gridの仕様(?)が結構特殊な感じだったためφ(..)
f:id:TakasDev:20160518000634p:plain


Xamarin.FormsのAngerの内容を流用しているため、Xamlの話ではありません。

www.syntaxismyui.com


AngerのCardsの画面の作り方、結構好きなんですが

これ、Xamlで作るにはどうしたらいいんですかね?さっぱり想像つきません…

Grid

Grid grid = new Grid
{
    RowSpacing = 1,
    ColumnSpacing = 1,
    BackgroundColor = UserPageStyleKit.CardBorderColor,
    VerticalOptions = LayoutOptions.FillAndExpand,
    RowDefinitions =
    {
        new RowDefinition { Height = new GridLength(80, GridUnitType.Absolute)},
        new RowDefinition { Height = new GridLength(50, GridUnitType.Absolute)}
    },
    ColumnDefinitions =
    {
        new ColumnDefinition { Width = new GridLength(100, GridUnitType.Absolute)},
        new ColumnDefinition { Width = new GridLength ( 1,GridUnitType.Star)},
        new ColumnDefinition { Width = new GridLength ( 10,GridUnitType.Absolute)},
        new ColumnDefinition { Width = new GridLength ( 140,GridUnitType.Absolute)}
    }
};

上記で2行4列のGridとなります。

下図の様なGridの配置となります。

f:id:TakasDev:20160518001048p:plain

それぞれGridLengthが指定されていますが、紫色背景の列は

GridUnitType.starが指定されているため、表示領域により動的に幅が変わるようです。

例えば、下記のようにソースを変更すると、1:2で描画されるようです。

ColumnDefinitions =
{
    new ColumnDefinition { Width = new GridLength(100, GridUnitType.Absolute)},
    new ColumnDefinition { Width = new GridLength ( 1,GridUnitType.Star)},
    new ColumnDefinition { Width = new GridLength ( 2,GridUnitType.Star)},
    new ColumnDefinition { Width = new GridLength ( 140,GridUnitType.Absolute)}
}

f:id:TakasDev:20160518001228p:plain

Grid要素の配置

Gridに対する要素の配置は、下記のようなソースで行っています。

grid.Children.Add(new Label { Text = "(0,1,0,1)", BackgroundColor = Color.Black }, 0, 1, 0, 1);
grid.Children.Add(new Label { Text = "(1,2,0,1)", BackgroundColor = Color.White }, 1, 2, 0, 1);
grid.Children.Add(new Label { Text = "(2,3,0,1)", BackgroundColor = Color.Blue }, 2, 3, 0, 1);
grid.Children.Add(new Label { Text = "(3,4,0,1)", BackgroundColor = Color.Pink }, 3, 4, 0, 1);
grid.Children.Add(new Label { Text = "(0,1,1,2)", BackgroundColor = Color.Silver }, 0, 1, 1, 2);
grid.Children.Add(new Label { Text = "(1,2,1,2)", BackgroundColor = Color.Purple }, 1, 2, 1, 2);

Text要素が、上図の(x,x,x,x)で表記されている内容です。

下図のような感じの考えたでしょうか?(手書き汚くてすみません)

f:id:TakasDev:20160518001432p:plain

なので、(0,1,0,2)と指定してやることで

下図のようにRowをまたがった描画も可能となります。

f:id:TakasDev:20160518001456p:plain

ただし、下記のように描画箇所がバッティングを起こすと

後に宣言されたものが優先して描画されます。

grid.Children.Add(new Label { Text = "(0,1,0,2)", BackgroundColor = Color.Black }, 0, 1, 0, 2);
grid.Children.Add(new Label { Text = "(0,1,1,2)", BackgroundColor = Color.Silver }, 0, 1, 1, 2);

f:id:TakasDev:20160518001551p:plain

Column数以上の数値を指定したとき

ここ、少し戸惑いました。

基本形を下図とします。

f:id:TakasDev:20160518001712p:plain

grid.Children.Add(new Label { Text = "(3,5,0,2)", BackgroundColor = Color.Blue }, 3, 5, 0, 2);

上記コードを突っ込んだときエラーになるかというとなりませんでした。

下図のようになります。

見にくいですが、2/3列目が縮小されています。
f:id:TakasDev:20160518001805p:plain

2/3列目をAbsolute属性に変更し、同様のソースで実行したところ

下図のようになりました。
f:id:TakasDev:20160518002002p:plain

領域をフルに活用して描画するようになっているのでしょうか?

Column数が拡張されているように見受けられます。

ちなみに、下のようなソースで実行した場合

grid.Children.Add(new Label { Text = "(4,100,0,1)", BackgroundColor = Color.Maroon }, 4, 100, 0, 1);
grid.Children.Add(new Label { Text = "(4,20,1,2)", BackgroundColor = Color.Maroon }, 4, 20, 1, 2);

下図のような描画となります。
f:id:TakasDev:20160518002250p:plain

残領域で100カラム作っているんですかね?

Gridのここらへんの動作分かってないと

ほぼエラーが発生しないんでドツボにはまることになるかもしれません。

まとめ

気を付けなければいけない部分はありますが

Gridを活用すれば、イケている画面を作成する余地は十分にありそうです。

Congnitive Serviceを使ってみる - App実行編(Adult検証) -

続きです。

完全に釣りタイトルかもしれませんが

VisionがXamarinでも使用できるのであれば

顔認識系のアプリもさくっとできるかもしれない。

というかそれがしたいがために、このサービスの検証をしています。

「Adult」はAPIの中にあったんで、気になって検証しました。

だって男の子ですし

コンソールアプリケーションで試す(Code)

以下のサイトを参考にコンソールからCongnitive Serviceを使用してみます。

Microsoft Cognitive Services - Documentation

NuGetでVisionを取得
f:id:TakasDev:20160508032259p:plain

ソース

VisionServiceClient VisionServiceClient = new VisionServiceClient({SUBSCRIPTION_KEY});
AnalysisResult analysisResult;

using (Stream imageFileStream = File.OpenRead({FILE_PATH}))
{
    VisualFeature[] visualFeatures = new VisualFeature[] { VisualFeature.Adult, VisualFeature.Categories, VisualFeature.Color, VisualFeature.Description, VisualFeature.Faces, VisualFeature.ImageType, VisualFeature.Tags };
    analysisResult = await VisionServiceClient.AnalyzeImageAsync(imageFileStream, visualFeatures);
}

これだけです。

これだけでComputerVisionの恩恵をあずかれるのは素晴らしいですね。

動かしてみる

自分の写真を使ってみました(実際に目線はないしサイズももうちょっとでかいです)

・こんなん
f:id:TakasDev:20160508032504p:plain

実行結果
f:id:TakasDev:20160508032714p:plain

きちんと返ってきました。中身も色々と興味深いです。

現在年齢は27、1歳など誤差の範囲なので、いい感じの認識能力です。

GenderはFemale??

MSでは、Female=男なの?と訝しみ、Bingで翻訳してみましたが「女性」と出ましたので

やはり、自分はMS的には女性として認識されているようです。
(日本人の顔認識は苦手なのかな?)

「Adult」が気になる
f:id:TakasDev:20160508032545p:plain

IsAdultContent = False?

もしかして、これ画像が成人コンテンツか判断しているのか?

気になるので検証してみました。

いざAdult検証

というわけで、検証のため、検証のため

肌色多めのあだるてぃな画像を用意して検証してみました。
(さすがに画像は載せれません)

結果
f:id:TakasDev:20160508033210p:plain
Adult認証!

やはり画像が成人コンテンツかどうか判定するものなんですね。

ちなみに、↓みたいな肌色一色の画像はFalseになりました。結構有能っぽいです。
f:id:TakasDev:20160508033350p:plain

ちょっと真面目にAdult考察

まぁ画像1・2個試しただけなので、その精度はいかがなものか?というのもありますが

お子さん向けのアプリケーションで、フィルタをかけるのにいいかもしれません。

また、MobileApp系の審査って、成人コンテンツに敏感なイメージがあります

Upload&閲覧系のアプリケーションの成人コンテンツのブロックにもいいかもしれませんね。

しかし、2次元とか水着とか肌の色がアバターとか着衣とかどうなるんだろう…?

明日にでも試そうと思います。んでXamarinの人柱erに戻ります。

今日はもう限界なのでここまで。

Congnitive Serviceを使ってみる - 導入編 -

JXUGとても楽しかったです。

色々と昂ってきたので、冷めやらないうちに色々やろうと思います。

とりあえずCongnitiveServieを!(ぇ

準備

CongnitiveServieのトライアル版を下記サイトで試すことができます。

www.microsoft.com


f:id:TakasDev:20160508025925p:plain
「GetStartedFree」からトライアル版の申し込みが可能です。

Microsoftアカウントが必要となりますので、ない人は事前に取得が必要です。

登録が完了すると「MyAccount」から登録したプロダクトの確認が行えます。

プロダクトの確認画面
f:id:TakasDev:20160508030057p:plain

Preview版は下記の通りの制限があるようです。

Face:30,000トランザクション/月 20回/分

ComputerVision:5,000トランザクション/月 20回/分

APIの動作の確認

使用の仕方はAPIのリファレンスがあるので↓を参考に。
Microsoft Cognitive Services

上記ページの「OPEN API TESTING CONSOLE」から

コード記述なしで実際の動きを確認することができます。

TESTING CONSOLE画面
f:id:TakasDev:20160508030446p:plain

  • VisualFeatures:顔認識の「Face」を選択。
  • Subscription-Key:上図の「MyAccount」画面で表示されるKey。
  • RequestBody:顔認識を行いたい画像のURLを指定。


画面下部の「Send」押下で処理が実行されます。

実行結果
f:id:TakasDev:20160508030754p:plain

結果は、上記に様に返却されます。

今回は1万円の諭吉さんの画像を使用したので

年齢・性別ともに、いい感じに認識できていると思います。

あとはJson.Netを使用して

ほしい情報を引っこ抜けばいいわけですね。


長くなるので「App実行編」に続きます。

EmployeeDirectoryを弄ってみた

以前に書いた通り、EmployeeDirectoryのマージをしました。

ただ、思った以上にサンプルとしては内容が盛りだくさんな感じなので

ポイント部分と動作イメージだけさらっと

結果として、EmployeeDirectoryは入門編にはちょうどいい感じがしました。

構成

サンプルのソリューションの構成が今までのと違います。

UIとビジネスロジックをソリューションから分離している感じですね。
f:id:TakasDev:20160504192527p:plain
というかこのサンプル、ログイン画面込みの構成なんで

最初からこれを使えばよかった…と思ったのは別の話。

一応自分が作ったマージするほうも同様に、下図の様にUIとロジックで分離しました
f:id:TakasDev:20160504192701p:plain

これ関係ぜんぶ書き出すとめちゃくちゃ長くなりそうなので

一部だけ

ログイン画面の遷移

App.cs内の初期ページの指定として、ログイン画面ではなくMain画面を指定します

App.cs

public App()
{
    var task = Task.Run(async () => {
        //CSVをメモリに格納
        Service = await MemoryDirectoryService.FromCsv("XamarinDirectoryTemp.csv");
    });
    task.Wait();
    //ログインページではなくMainPageを指定
    MainPage = new NavigationPage(new MainPage());
}

また、上記で指定したMainPage.csのOnAppearingイベント内で

LoginPageをPush表示します。

これで、App起動時にLogin画面が開かれることになります。

MainPage.cs

protected async override void OnAppearing()
{
    base.OnAppearing();

    if (LoginViewModel.ShouldShowLogin(App.LastUseTime))
    {
        if (!LoginPageAdd) { 
            LoginPageAdd = true;
            //ログインページを表示
            await Navigation.PushModalAsync(new LoginPage());
        }
    }
    favoritesRepository = await XmlFavoritesRepository.OpenIsolatedStorage("XamarinFavorites.xml");

    if (favoritesRepository.GetAll().Count() == 0)
    {
        favoritesRepository = await XmlFavoritesRepository.OpenFile("XamarinFavorites.xml");
    }
    viewModel = new FavoritesViewModel(favoritesRepository, true);
}

ログイン成功時はPopModaiAsyncでMain画面に戻ります。

※単純にこの実装だけだと、Androidの「戻る」ボタン押下で
Main画面を見れてしまうのですが(^^;)
まぁその制御はおいおい。

PCLStorage

このサンプルでは、端末のローカルストレージにCSVファイルを落とし

CSVの内容からLINQでUserViewModelの配列を生成しています。

端末のローカルストレージに落とす場合

AndroidiOSで使用するAPIが違うのでしょうが

PCLStorageの機能を使用して

同一のロジックでファイル操作を行っているようです。

MemoryDirectoryService.cs

public async static Task<MemoryDirectoryService> FromCsv(string path)
{
    //PCLStorage機能を使用しファイル操作
    IFolder store = FileSystem.Current.LocalStorage;
    var file = await store.GetFileAsync(path);

    using (var reader = new StreamReader(await file.OpenAsync(FileAccess.Read)))
    {
        return FromCsv(reader);
    }
}

これは↓に格納されるようです。
f:id:TakasDev:20160504193938p:plain

動作させた

ログイン後はMasterDetailページとなります。

MasterDetailのサンプル画面から
f:id:TakasDev:20160504194110p:plain

EmployeeListの画面に遷移します。
(サンプルから中身弄ってないんで頭だけ出しときます)
f:id:TakasDev:20160504194137p:plain

まとめ

ページ遷移からファイル操作、ViewModelを使用したMVVMな作り等

EmployeeDirectoryのサンプルは盛りだくさんといった感じです。

なので、とっかかりとしてやる分には非常にいいのではないかな?

と思います。

備忘録:Xamarin系

Link貼り間違えてました…ので修正。

とりあえず、Xamarin.Formsで色々やりたいこと調べたので備忘録的にφ(..)

Xamarin.FormsでPopUpViewを出したいときに使えそう

github.com

SearchBarの使い方

www.syntaxismyui.com

Xamarin.Formsのイケてるデザイン指南?

www.syntaxismyui.com

Xamarin.Formsコントロールのチートシート

blog.xamarin.com

Xamarin.Formsのサンプルで遊んでみたよ!

Evoleve2016始まりましたね!

どんな発表があるかドキドキですね!

サンプルで遊ぶ

Hello, iOSですとかHello Androidもいいですけど

実際にゴリゴリ動いているのを見るとソースをいじるのが楽しくなりますよね。

今回、Xamarin.FormsのGitHubで提供されている、2つのSampleを組み合わせて遊んでみました。


github.com


今回組み合わせたサンプル2つ
xamarin-forms-samples/Navigation/LoginFlow/

xamarin-forms-samples/Navigation/MasterDetailPage/

使用しているサンプル名称を見ていただければわかる通りですが

ログイン画面でログイン→MasterDetailページに遷移

といった単純な構成です。とっかりりとしてはこれぐらいがちょうどいいですね。

※MasterDetailPageの構成なんかは、上記のGitHub内にScreenShotがありますのでご覧くださいませ。

まずはサンプルソースをざっと眺めてみる

LoginFlow

開いて早速エラーが出まくったり、MVVMチックな構成ではなかったりと

気になるところは多々ありますが、サンプルを下敷きに新しく作り直せば問題ありません。

LoginPageCS.cs
LoginPage.xaml
まず上の2つのファイルがその名の通りLoginPageのView部分ですね

C#のコードのみでも構成できますし、XAMLを使用することも可能です。

WPF使いの方ならXAML安定ですね。


Sampleを組み合わせるうえでLogInPage側の肝のLogicは下記部分ですね。
(実際には色々基本的な部分で重要な部分はいっぱいありますよ!)

LoginPage.xaml,cs

async void OnLoginButtonClicked (object sender, EventArgs e)
{
	var user = new User {
		Username = usernameEntry.Text,
		Password = passwordEntry.Text
	};

	var isValid = AreCredentialsCorrect (user);
	if (isValid) {
		App.IsUserLoggedIn = true;
		Navigation.InsertPageBefore (new MainPage (), this);
		await Navigation.PopAsync ();
	} else {
		messageLabel.Text = "Login failed";
		passwordEntry.Text = string.Empty;
	}
}

入力されたユーザー名称とパスワードが一致しますかー?というものを確認。

Navigation.InsertPageBeforeで遷移先のページを生成し、Navigation.PopAsyncでページ遷移を行っています。

今回やりたいのは、このMainPageをMasterPageDetailのSampleで使用されているMain画面にするだけです。

MasterDetailPage

こちらはLogic部分で変更する箇所はありません。

ただ、押さえておきたいのは、下記の内容です。

MainPage.xaml

<?xml version="1.0" encoding="UTF-8"?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms" 
				  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
				  xmlns:local="clr-namespace:MasterDetailPageNavigation;assembly=MasterDetailPageNavigation"
				  x:Class="MasterDetailPageNavigation.MainPage">
  <MasterDetailPage.Master>
  	<local:MasterPage x:Name="masterPage" />
  </MasterDetailPage.Master>
	<MasterDetailPage.Detail>
		<NavigationPage>
			<x:Arguments>
				<local:ContactsPage />
			</x:Arguments>
		</NavigationPage>
	</MasterDetailPage.Detail>
</MasterDetailPage>

CSのコードハイライトはちと役不足感があるけどまぁいいか

MainPage.xaml.cs

public MainPage ()
{
	InitializeComponent ();

	masterPage.ListView.ItemSelected += OnItemSelected;

	if (Device.OS == TargetPlatform.Windows) {
		Master.Icon = "swap.png";
	}
}

void OnItemSelected (object sender, SelectedItemChangedEventArgs e)
{
	var item = e.SelectedItem as MasterPageItem;
	if (item != null) {
		Detail = new NavigationPage ((Page)Activator.CreateInstance (item.TargetType));
		masterPage.ListView.SelectedItem = null;
		IsPresented = false;
	}
}

MainPageがMasterとDetailに分かれており、それぞれページが指定されています。

Maseterがわが「MasterPage」Detail側が「ContactsPage」です。

リストアイテムの選択処理はMasterPage(子)のCSではなく、MainPage(親)で行われています。

XAML側7行目で配置された、MasterPageに配置されたListViewのEventをキャッチし、選択処理が行われています。

NavigationPageでページ遷移を行っています。

item.TargetTypeはMainPageやContentPage等のXAMLで作成したページ名称ですね。

では組み合わせてみよう

前述の通り、Sampleをそのままですとエラーが多すぎるため

新しいソリューションを立ち上げて、ソースを組み合わせていきます。

途中過程はすっとばしまして、ソリューションの構成は下記の通りです。
f:id:TakasDev:20160424235640p:plain

MVVMっぽい構成になりました。

Mock内にはSampleUserをつっこんでます。

ViewModel内には、UserViewModelとMenuのViewModelですね。

Xamarin.Droid,/iOsにはResourceとして、アイコン情報を登録しただけです。

Droidは \Resources\drawableに

iOSは \Resourcesに格納しました。

デバイス側にはコードを1行も記述していないです。スバラシイ

実行

f:id:TakasDev:20160425000959p:plain

ログインページでた!

が、ログイン処理時にエラー!!
f:id:TakasDev:20160425001100p:plain

やはりすんなりはいかないか…

エラーの内容を確認すると

「Navigationページは1ページ1個しか認めませんよ!」という内容のようです。

そりゃそうだ。

では、ここでXAMLを見ていきます。

たしかに、MasterDetailを使用しているMainPage.xamlタグを使用しています(上述参照)。

しかし、LoginPageにはタグは存在しません。

では、どこにあるのでしょうか。

App.cs

public App()
{
    if (!IsUserLoggedIn)
    {
        MainPage = new NavigationPage(new LoginPage());
    }
    else
    {
        MainPage = new NavigationPage(new MainPage()); ;
    }
}

App.csでアプリケーション立ち上げ時のページを指定していますが

ここの部分で、LoginPageがNavigationPageとしてNewされています。

だから、ログインアクション時の、「Navigation.InsertPageBefore (new MainPage (), this)」が使用できるわけですね。

対処療法的に対処してみる

変更後のMainPage.xaml

<?xml version="1.0" encoding="UTF-8"?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
				  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
				  xmlns:local="clr-namespace:XamarinSample.Views;assembly=XamarinSample"
				  x:Class="XamarinSample.Views.MainPage">
  <MasterDetailPage.Master>
    <local:MasterPage x:Name="MasterPage" />
  </MasterDetailPage.Master>
  <MasterDetailPage.Detail>
    <!--<NavigationPage>-->
    <!--<x:Arguments>-->
    <local:ContactsPage />
    <!--</x:Arguments>-->
    <!--</NavigationPage>-->
  </MasterDetailPage.Detail>
</MasterDetailPage>

完全に対処療法ですが

すでにLoginPageからNavigationを使用したページ遷移が行われているわけですし

改めてNavigationPageタグの宣言する必要ないよね?ってことでNavigationタグを消してみました。

ログイン通った!

f:id:TakasDev:20160425002645p:plain

MasterDetail側のページ遷移もうまく動作しているようです。

f:id:TakasDev:20160425002755p:plain


いや、でも対処療法だし、もうちょっとちゃんと眺めようとは思います。

まとめ

  • Sampleソースは見るのもいじるのも勉強になります。
  • いきなり作りたいものを作るより、Sampleを組み合わせるほうがイメージしやすいかも?

EmployeeDirectoryのSampleを流用して、ユーザー管理画面を作ってみようかなと考えています。

あぁ、でもBotFrameworkも気になってるんですよね

まぁ、明日から月曜なんで、遊ぶのはしばらくお預けです…。

ものすごい長くなったんで次回は抑えれるよう頑張ります。