読者です 読者をやめる 読者になる 読者になる

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

.Net系プログラムで勉強したこととか嵌ったことについて書いたりします。

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について

Xamarin

下図の画面を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検証) -

Congnitive Service

続きです。

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

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を使ってみる - 導入編 -

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を弄ってみた

Xamarin

以前に書いた通り、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も気になってるんですよね

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

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