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

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

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も気になってるんですよね

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

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

Xamarinを初めて見た

Xamarinが無償化されて幾週間。

自分が嵌った所やら、勉強に使用したものをまとめてみます。

 

環境設定

正直、Xamarinで一番何が嵌ったかといわれると環境設定のような気がします。

ベース部分は、エクセルソフトの田淵さんが書かれた、下記のサイトが非常に参考になりました。

テンプレートについても非常に有り難かったです。

「読んでほしい」とありますが「必読」です。

ytabuchi.hatenablog.com

 Windows10 + VisualStudio Emuratorが鉄板?

鬼門だったのはXamarin Android Player。

元々Win7でやろうとしていたので、導入しようとしていたのですが

VirtualBoxの最新Ver.から、VBox Commnad Failedでまともに動作せず

(うぶんつちゃんすら動かなかった…)

VirtualBoxの5.0.0.0を導入する羽目に。

ただ、旧Ver.を入れ続けることにも抵抗はあったし

Win10+VSEmuratorで動作は確認済みだったため

(早く弄りたいこともあり)Win10側をメインに転向しました。

 

Win7機2台ほどで試したのですが

両方同様にXAPの環境設定で嵌ったため

PCの環境依存によるものとしても

Win10を使用するのが一番安定するのかなぁ。と感じました。

 

VSEmuratorについては、標準Emuratorから比べると圧倒的によい動作なので

特に気にせず使用できる感じです。

 

次回はGitHubで公開されている

Xamarin.Formsのサンプルで遊んだ内容について記述しようと思います。