Neutral Scent

App developments & Gadgets

サンプルコードを見ながら理解するMVVMの基礎的な実装


WPFがWinFormsより敷居が高い?
そりゃ、最初に掛け違ってるからですよ、きっと。

というわけで、これはXAML Advent Calendar 2014の3日目、12月3日分のエントリーです。WPF? XAML? MVVM? そんなにムズカシクないよ? というお話。
もちろんWinRTのWindowsストアアプリやWindows Phoneアプリ等、XAMLベースのプラットフォームにもほとんどすべて共通した内容です。
ここではあえて理論とか観念は説明しません。とにかくコードを見ながら仕組みと動きを理解していきます。
俺は、コードが読める、長い説明エントリーなんてめんどくせぇ、と思ったら、コード部分だけを実際に動かしながら見ていくだけでも基本的な構造が十分に理解できるのではないか、と。


サンプルプロジェクト
Download: SimpleMVVM.zip 直
github: https://github.com/kaorun/kaorun_samples/tree/master/SimpleMVVM
ビルドして実行すると表示されるこちらのインデックスから順にサンプルとして紹介していきます。



Simple Model Binding
まずは、おなじみのPersonクラスから。
Person.cs

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

まぁ、よくあるサンプルですよね。MVVMやMVCパターンで言うところのいわゆるModelです。
これをXAMLを使って表示すると、だいたいこんな実装になります。
SimpleModelPage.xaml

<StackPanel>
    <TextBlock Text="First Name:"/>
    <TextBox Text="{Binding FirstName}"/>
    <TextBlock Text="Last Name:"/>
    <TextBox Text="{Binding LastName}"/>
    <TextBlock Text="Age:"/>
    <TextBox Text="{Binding Age}"/>
</StackPanel>

こちらが表示側にあたる、いわゆるViewですね。
TextBoxコントロールのText属性を{Binding 〜}というマークアップ拡張構文でオブジェクトに紐づけています。
<TextBox Text="{Binding FirstName}"/>であればTextBoxコントロールのTextプロパティにFirstNameプロパティを紐づけ(Binding)するよ、という定義です。
このようにViewをXMLで定義して実装するためのマークアップ言語として開発されたのがXAMLです(実際には汎用的に様々なオブジェクトをXMLで定義することができるため、多くの用途にXAMLが利用されるようになっています)。
追記: いちおう.NET界隈でない人に説明しておくと、SimpleModelPage.xamlSimpleModelPage.xaml.csの2つはいわゆるpartialクラス定義です。XAMLはオブジェクト定義に変換されるので、クラスの定義を複数の構文に分割できるpertialクラスにより*.xamlと*.xaml.csで一つのViewオブジェクトクラスを定義しているわけですね。*.xaml.csはHTMLでいうところのscriptタグみたいなイメージで。
そのままでは出ないので、とりあえず、Pageのコンストラクターインスタンスを生成して、DataContextに突っ込んでいます。このViewのコンテキスト、つまりは表示するためのデータはこれ、というわけですね。これは、とりあえず、お約束ということで。
SimpleModelPage.xaml.cs

public partial class SimpleModelPage : Page
{
    public SimpleModelPage()
    {
        InitializeComponent();

        var p = new Person()
        {
            FirstName = "Tadafumi",
            LastName = "Iriya",
            Age = 17,
        };

        this.DataContext = p;
    }
}

入谷君をイジって楽しむよ(何)。

実行してみましたか? はい、出ましたね。

  1. 表示するためのクラスを定義
  2. インスタンスを生成
  3. ページ(View)のDataContextに割り当て
  4. {Binding}構文を使ってコントロールのプロパティに割り当てる

これが、XAMLを利用したMVVMの礎の一つDataBindingの基本です。
しかし、これだけではとりあえず出るだけで、編集してもなにも起こりません。



Field Member Model Binding
それから、先のPersonクラス、なんでgetter/setterの付いたプロパティやねん? と思いませんでしたか? そう、シンプルなクラスだったら、フィールド変数なんじゃないの? と。
では、試してみましょう。
PersonFieldMember.cs

public class PersonFieldMember
{
    public string FirstName;
    public string LastName;
    public int Age;
}

どうでしょう? 表示されませんね。

つまり、Bindingを使うためのDataContextとなるクラスのメンバ変数は常にgetter/setterを持ったプロパティでなければならないという点です。後々でてくる話に繋がるのですが、とりあえずまず、これは約束です。大概、わかっていても実装を進めていると後述するCommandプロパティなどをうっかりフィールド変数で定義してしまい、「よ...呼ばれない、なんで!?」などとうろたえることになります。
とにかくBindする変数はプロパティで。



Update Model Binding
さて、クラスオブジェクトをViewで表示しているのなら、これをコードで変更したらView側も更新して表示してくれんの? と思いませんか?
早速、ボタンを置いて、Ageを加算してみましょう。
ModelIncrementAgePage.xaml

<StackPanel>
    <TextBlock Text="First Name:"/>
    <TextBox Text="{Binding FirstName}"/>
    <TextBlock Text="Last Name:"/>
    <TextBox Text="{Binding LastName}"/>
    <TextBlock Text="Age:"/>
    <TextBox Text="{Binding Age}"/>
    <Button x:Name="cmdIncrementAge" Click="cmdIncrementAge_Click" >Age++</Button>
</StackPanel>

Personインスタンスをクラスメンバー化して、とりあえず、ボタンの処理はえいやでコードビハインドのClickイベントで実装です。
ModelIncrementAgePage.xaml.cs

public partial class ModelIncrementAgePage : Page
{
    private Person p;

    public ModelIncrementAgePage()
    {
        InitializeComponent();

        p = new Person()
        {
            FirstName = "Tadafumi",
            LastName = "Iriya",
            Age = 17,
        };

        this.DataContext = p;
    }

    private void cmdIncrementAge_Click(object sender, RoutedEventArgs e)
    {
        p.Age++;
    }
}

さて、実行してボタンを押してみます。

うーん、何も起きませんね。デバッグしてみるとわかりますが、コードは実行されているはずです。つまりPersonクラスのAgeプロパティは増えているのに、View側の画面には反映されません。
WinFormsなどコードビハインドで実装していたら、

private void cmdIncrementAge_Click(object sender, RoutedEventArgs e)
{
    p.Age++;
    textAge.Text = p.Age.ToString()
}

などと実装するところですが、今このサンプルで更新するためのコードは書いてない、つまりDataContextに割り当てたオブジェクトの変更をViewがBindingで勝手に更新してくれたりはしないのです。



Update ViewModel Binding
では、どうするか?
クラス側で、どの変数が変更されたよ、という情報を通知するイベントを用意してやります。
PersonViewModel.cs

public class PersonViewModel : INotifyPropertyChanged
{
    private string firstNameVal;
    public string FirstName
    {
        get { return firstNameVal; }
        set
        {
            firstNameVal = value;
            NotifyPropertyChanged("FirstName");
        }
    }

    private string lastNameVal;
    public string LastName
    {
        get { return lastNameVal; }
        set
        {
            lastNameVal = value;
            NotifyPropertyChanged("LastName");
        }
    }

    private int ageVal;
    public int Age
    {
        get { return ageVal; }
        set
        {
            ageVal = value;
            NotifyPropertyChanged("Age");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

実行すると、ボタンの押下で入谷君の年齢がどんどん上がっていきます。下げる機能はまだありません。

さて変わったところはなんでしょう?
INotifyPropertyChangedというインターフェイスを継承して、各プロパティになにやらがしゃがしゃとコードが追加され、最後に見知らぬメンバーとしてイベントとプライベートメソッドが追加されています。
追加されたINotifyPropertyChangedインターフェイスとはなんでしょう? 定義を見てみます。

namespace System.ComponentModel
{
    // 概要:
    //     プロパティ値が変更されたことをクライアントに通知します。
    public interface INotifyPropertyChanged
    {
        // 概要:
        //     プロパティ値が変更されたときに発生します。
        event PropertyChangedEventHandler PropertyChanged;
    }
}

ようするに、クラスにイベントを一つ追加実装しなさいよ、という決まりです。

なにをやってるかはコードを読めばわかると思いますが、今どの変数が変更されたよ、という通知を送ってるわけですね。いわゆるObserverパターンのオブザーバー実装です。
シンプルなPersonクラスに変更通知機能が付いた、これがViewのためのModelオブジェクト、ViewModelの基礎の基礎です。実際のプロパティやNotifyPropertyChanged()実装では様々なテクニックや実装が使われることになりますが、基本的な動作としてはここがベースになります。



Edit Model Binding
さて、今度はよりViewModelらしい動きを実装するためにフォームの編集機能を追加します。FirstName, LastNameときたらFullNameですよね。ということで、まずは試しにModelクラスのPersonクラスにFullNameプロパティを実装してみます。
PersonFullName.cs

public class PersonFullName
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName
    {
        get { return FirstName + " " + LastName; }
        set
        {
            var names = value.Split(new[] {' '});
            if (names.Length == 2)
            {
                FirstName = names[0];
                LastName = names[1];
            }
            else
            {
                FirstName = value;
                LastName = "";
            }
        }
    }
    public int Age { get; set; }
}

とうぜん、編集したところで更新されません。



Edit ViewModel TwoWay Binding
ではViewModelでは?
PersonFullNameViewModel.cs

public class PersonFullNameViewModel : INotifyPropertyChanged
{
    private string firstNameVal;
    public string FirstName
    {
        get { return firstNameVal; }
        set
        {
            firstNameVal = value;
            NotifyPropertyChanged("FirstName");
            NotifyPropertyChanged("FullName");
        }
    }

    private string lastNameVal;
    public string LastName
    {
        get { return lastNameVal; }
        set
        {
            lastNameVal = value;
            NotifyPropertyChanged("LastName");
            NotifyPropertyChanged("FullName");
        }
    }

    public string FullName
    {
        get { return FirstName + " " + LastName; }
        set
        {
            var names = value.Split(new[] { ' ' });
            if (names.Length == 2)
            {
                FirstName = names[0];
                LastName = names[1];
            }
            else
            {
                FirstName = value;
                LastName = "";
            }
            NotifyPropertyChanged("FullName");
        }
    }

...
}

いよいよクラスがだいぶ長くなってきたので途中は割愛、先ほどのViewModelと基本的には同じ仕組み、変更されたら通知する、です。
FirstNameを変更したらFullNameの変更も通知しているのがキモですね。

それから、XAML側も実はいろいろ変わっています。
EditFullNamePage.xaml

<StackPanel>
    <TextBlock Text="Press [Tab] key or change focus to Update"/>
    <TextBlock Text="First Name:"/>
    <TextBox Text="{Binding FirstName,Mode=TwoWay}"/>
    <TextBlock Text="Last Name:"/>
    <TextBox Text="{Binding LastName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Text="Full Name:"/>
    <TextBox Text="{Binding FullName,Mode=TwoWay}"/>
    <TextBlock Text="Age:"/>
    <TextBox Text="{Binding Age,Mode=TwoWay}"/>
</StackPanel>


{Binding FirstName}
から
{Binding FirstName,Mode=TwoWay}
へ、
{Binding LastName}
の方には、なにやらさらに長く、
{Binding LastName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}
とついていますね。
Mode=TwoWayは、View側での変更をViewModelへ反映するよ、という属性です。規定値はMode=OneWayなんですね。
そして、UpdateSourceTrigger=PropertyChangedは、ViewModelへの反映をするタイミングの設定です。
試しに、FirstNameとLastNameをそれぞれ変更してみてください。FirstNameは入力してもすぐにはFullNameが変わらず、タブキーなどでFirstNameコントロールからフォーカスが外れると更新されます。LastNameコントロールは入力している傍から変更が反映されますね、そういう属性です。
Binding属性にはこれ以外にもStringFormatなど様々な設定が可能なので、色々変更して試してみるといいでしょう。



Command Binding
さて、View側のフォームを変更してViewModelに反映させることができるようになりました。
ただ、先ほどの加齢ボタンのように、コードビハインドを書いてView側で値を出し入れしたりするのはなんだかカッコ悪い、ボタンクリックなどのコマンドもViewModel側で実装してBindingできないの?
...というわけで、今度はCommandバインディングです。

ViewModelがさらににぎやかになりました。
PersonCommandViewModel.cs

public class PersonCommandViewModel : INotifyPropertyChanged
{
    public ICommand IncrementAge { get; set; }
    public ICommand DecrementAge { get; set; }
    public ICommand Submit { get; set; }

    public PersonCommandViewModel()
    {
        IncrementAge = new RelayCommand(() => { Age++; });
        DecrementAge = new DecrementAgeCommand(this);
        Submit = new RelayCommand(SubmitNow);
    }

    private void SubmitNow()
    {
        MessageBox.Show(string.Format("User: {0}\nAge: {1}\nSubmitted!", FullName, Age));
    }
...
}

IncrementAge, DecrementAge, Submitコマンドが定義されました。謎のICommandインターフェイスインスタンスが定義されています。
また、View側のXAMLでは、ボタンのCommand属性にそれらのコマンドがBindingされています。
CommandPage.xaml

<StackPanel>
    <TextBlock Text="First Name:"/>
    <TextBox Text="{Binding FirstName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Text="Last Name:"/>
    <TextBox Text="{Binding LastName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Text="Full Name:"/>
    <TextBox Text="{Binding FullName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Text="Age:"/>
    <TextBox Text="{Binding Age,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
    <StackPanel Orientation="Horizontal">
        <Button Command="{Binding IncrementAge}">Age++</Button>
        <Button Command="{Binding DecrementAge}">Age--</Button>
    </StackPanel>
    <Button Command="{Binding Submit}">Submit!</Button>
</StackPanel>

しかし、そのおかげで、CommandPage.xaml.csのコードビハインドはインスタンスの生成だけですっきりしました。最初のサンプルと同じですね。
CommandPage.xaml.cs

public partial class CommandPage : Page
{
    public CommandPage()
    {
        InitializeComponent();

        var p = new PersonCommandViewModel()
        {
            FirstName = "Tadafumi",
            LastName = "Iriya",
            Age = 17,
        };

        this.DataContext = p;
    }
}

ViewModelがICommandを実装して、そのプロパティがViewのCommand属性にBindingされると、ViewがViewModelを呼び出せるようになるわけです。
ICommandはちとややこしいので、3つのボタンに対してそれぞれ違う実装をしてみています。

public PersonCommandViewModel()
{
    IncrementAge = new RelayCommand(() => { Age++; });
    DecrementAge = new DecrementAgeCommand(this);
    Submit = new RelayCommand(SubmitNow);
}

一番最初のIncrementAgeコマンドは単純ですね、ラムダ式でAge++をしているだけです。割り当てているRelayCommandについては後述。
だったら、コードビハインドみたいに単にメソッドを渡せばいいんじゃないの? と思われるかもしれませんが、次のDecrementAgeコマンドに割り当てられているDecrementAgeCommandクラスの実装を見てみてください。

public class DecrementAgeCommand : ICommand
{
    private PersonCommandViewModel vm;

    public DecrementAgeCommand(PersonCommandViewModel viewmodel)
    {
        vm = viewmodel;
    }

    public bool CanExecute(object parameter)
    {
        return vm.Age > 0;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        vm.Age--;
    }
}

ICommandをシンプルに実装するとこういう感じになります。
単に、コマンドが実行された場合だけでなく、ボタンの状態が今有効かどうか(無効なら自動的にグレる)、そして(ここでは未実装ですが)その状態が変わったことをイベントとして通知する仕組みも持っているわけです。
このICommandを都度々実装するのがめんどくせぇ、というのがRelayCommandクラスなわけですが、なぜか、こいつは.NET Frameworkの標準クラスではありません。Commonフォルダに入っているRelayCommand.csの実装は、Windowsストアアプリテンプレートに自動的に入ってくるRelayCommandのほぼ丸写し実装です。この辺りがなんで標準でないかは今回は割愛。RelayCommandもわりと高性能なので、引数で有効無効の実装などもできます。



今回作成したサンプルは以上です。
出来上がったコードを見てみると、MVVMによるアプリ実装とは、表示するためのViewModelクラスを定義して、XAMLで定義したViewにBindingしていくことが基本である、ということがご理解いただけると思います。
そして、表示するオブジェクトがViewModelに集約され、動作の流れが見えてくると、手続き型のコードビハインド実装が生み出すスパゲティコードがどのように回避されるのかもなんとなくわかってくるのではないでしょうか?
ただのプロパティなのにNotifyPropertyChanged()等をいちいち実装するのがめんどくせぇ、と思うかもしれませんが、そこはIDEパワーでコードスニペットを定義して力技で行きましょう。
本当は、INotifyPropertyChangeによるViewModelとはまた別にDipendencyObject(依存関係オブジェクト)とDependencyProperty(依存関係プロパティ)による通知システムも存在したりするのですが、ひじょーに長くてめんどい話になりますので、これまた割愛いたします。
さぁWPFWindowsストアアプリの勉強を始めよう、と、最初にVisual StudioのデザイナでUIを作り、コードビハインドを止めていざMVVMへ、ViewModelやらBindingやらを実装しようとすると、誤ってそちらの密林に足を踏み込んでしまい、厄介なことになることもあるのではないかと思うわけです。

さて、以上で駆け足で実装してきた、とにかく基礎的なMVVMアプリの説明は終了です。え? ViewModelがあるならModelいらないんじゃ? ModelとViewModelはどう切り分けるの? いやいや、そのあたりまで突っ込んで解説すると怖い人から鉞(マサカリ)が飛んできますからね...(まぁ、ここまででも十分飛んできそうだけども)。
まずは、動きとそれぞれの役割を把握してから、理論や応用に関して理解を深めてみるのもよいのではないでしょうか?

そういうわけで、くだくだと長い説明になってしまいましたが、MVVMってなんじゃい? という基本的なイメージを実装から理解していただければ幸いです。
それでは、今年も残り少なくなりましたが、皆さんに良いXAMLライフが訪れますように。

まとめ:

  • ViewをXMLで定義して実装するためのマークアップ言語として開発されたのがXAML
  • XAMLで定義したViewのDataContextに、Bindingを利用してViewModelを紐づけるのが(Windowsプラットフォームにおける)MVVMの基本
  • Bindingする変数はフィールド変数ではなく必ずget/setのプロパティで実装すること、これ約束な
  • ModelにINotifyPropertyChangedによる通知機能を追加してViewModelに
  • プロパティの更新をViewに反映するためにPropertyChangedイベントで通知する
  • ViewModelとは、通知機能を持ったObserverパターンの実装
  • ICommandインターフェイスを実装して、クリックなどの操作イベントもViewModelにBinding

Webページ翻訳アプリShrPageTranslatorを公開しました

http://www.windowsphone.com/ja-jp/store/app/shrpagetranslator/3f2c1d05-cd27-477e-b825-4ef7918e6d9f
ものすっごい単純なアプリなんですが、そういうの無いようなので作りました。

ShrPageTranslatorはWindows Phone 8/Windows 8で利用可能な共有コントラクトを利用したページ翻訳アプリです。
Internet Explorerや他のアプリからWebサイト(URL)を共有してShrPageTranslatorを選択すると、そのままそのアドレスをMicrosoft Translator(旧称Bing Translator)へリダイレクトします。それだけなのでとりあえず無料です。
対応環境: Windows Phone 8.1 / Windows 8.1

Windows Phone Storeからダウンロードする:
http://www.windowsphone.com/ja-jp/store/app/shrpagetranslator/3f2c1d05-cd27-477e-b825-4ef7918e6d9f
Windows Storeからダウンロードする:
http://apps.microsoft.com/windows/ja-jp/app/shrpagetranslator/1a2d13ac-df2f-421b-96cb-692dc270ab23
まぁ、ブックマークレットでもできることなのですが、IE Mobileのブックマークは色々アレなので、共有コントラクト(Windows 8だとチャームにある「共有」ってアレです)対応のNextGen ReaderなどのRSSリーダーやTweetiumなどTwitterクライアントで、英語や中国語のページが流れてきたときなどに便利かと思います。
基本現在のシステム既定の言語へ翻訳しますが、アプリを直接立ち上げると翻訳先の言語を選択できるので、Windows 10 TPなどメインを英語環境などで使っている場合はそちらで変更してください。3時間ぐらいで原型ができるだろう、と軽い気持ちで始めたら、累計でフルに3日ぐらいかかりました(汗)。
あ、それから、今回はグローバル向け優先で作ったので、とりあえず現状UIは英語版のみです。すべてのマーケットからダウンロードできますし、機能は単純なので迷うこともないかと思います。

日本の季節の行事をiCalendar形式でGoogleカレンダー/iCal/Outlookなどへインポートする


節分とかお彼岸、立春とか大寒冬至夏至とか、祝祭日ではないけど、一般的な日本の季節の行事ってあるじゃないですか? 二十四節気や雑節というらしいですが。
Google CalendarとかOutlook.comのカレンダーとか利用していると、祝祭日のデータはインポートできるけど、季節の行事もiCalendarでインポートできないかなー、とふと思ったんですね、で色々探してみたけど、意外と見つからない。iPhoneAndroidで参照したい人もいると思います。
で、結局、唯一見つかった国立天文台のカレンダーのイベントのインポート方法がちょっとトリッキーだったのでエントリーにしておきます。

国立天文台 天文情報センター 暦計算室
http://eco.mtk.nao.ac.jp/koyomi/

こちらの、今月のこよみ powered by Google Calendar をクリック。

で、カレンダーが表示されるので、右下の「+Googleカレンダー」ボタンをクリックすると、このカレンダーのイベントを自分のGoogleカレンダーにインポートできます。


すると、自分のGoogle Calendarが開き、インポートの選択画面が出るので、好みのカレンダーを「追加」。何度でもできます。
月食・日食や各種惑星現象などのイベントもあるので天文マニアの人などはお好みで。

というわけで、まずはGoogle Calendarにインポートできました。

さらに、追加したイベントを他のOutlookiCalなどでiCalendar形式のデータとしてインポートしたい場合は、左カラムの一覧から「カレンダー設定」を開き...

ical」ボタンを押下して表示されたURLをコピーして、Outlook.comなりOutlookなりiCalなりに食わせてやればインポートできるはずです。

ちょっとした設定ですが、あれ? 節分っていつだっけ? とかなりがちなので、「二十四節気・雑節」カレンダーだけでもインポートしておくと意外と便利ではないか、と。

Microsoft Bandだけじゃない! Microsoft HealthVaultを使ってみた


Microsoft Bandはやく来ないかなー、と物欲待機 状態で待ち構えていたところ、これなんだ? という感じで https://www.healthvault.com/jp/ja というアドレスがTLに流れてきました、おお、HealthVaultね、ん?? jp/ja!? いつのまに日本語対応されたの??
(追記: 日本語化されたのは2013年頃とのことです)
というわけで、早速登録出来たので使ってみました。

要約:

  • MicrosoftクラウドPHR(Personal Health Record)サービスがHealthVault
  • Microsoft Bandのデータ保存先となる
  • Web及び、iOS(iPhone/iPad), Android, Windows Phone, Windows Storeアプリ対応
  • Microsoft Bandだけでなく、サードパーティ製のFitbitや体組織計]などのフィットケアデバイス、血圧計などの計測器などかなり多数のデバイスに対応(活動量, 体重・体組織計, 血圧, 心拍, 血糖値, 酸素濃度,...)
  • サービス開始は意外と早く2007年
  • 個人のフィットネス・健康管理・医療記録などをすべて一元管理できる
  • Excel,CSV,TSVのデータをインポート可能
  • 特定の個人(メールアドレス)へ情報をShareしたり、医師に開示したりできる
  • 医療施設側からCCR/CCDフォーマットの開示データを受け取ることも可能
  • 緊急時に医療関係者のための緊急時プロファイルを作成可能
  • Webサービスは日本語化済、ほぼ遜色なく日本語でデータ入力できる


発表されたばかりのMicrosoft Bandと、ある意味、それと対になるクラウドサービスがMicrosoft HealthVault(ヘルスヴォルト)です。
いわゆるPHR(Personal Health Record)系のサービスで、 フィットネスデータだけでなく、健康管理・医療記録などをすべてを一元管理できます。言ってみれば柔軟なデータ形式を持つ健康系Webデータベースです。
クラウドサービス、しかもMicrosoftの運営するサービスに医療情報をすべてぶち込むなんて怖すぎるわ、という方、まぁ気持ちはわかります、そういう怖さを感じるならやめといた方がいいかもですね。一方で、一元管理するメリットも多分にあると思われますし、一元管理したいと思っていた方も少なからずおられるのではないでしょうか。
実は、HealthVaultに先行してGoogleGoogle HealthというPHRサービスを2007年から運営していたのですが、時代を先取りしすぎていたようで、2011年に採算が出ずに撤退しています。Google HealthもいずれAndroid Wear対応のサービスとして何らかの形で復活するのではないかと思いますし、AppleのHealthKitも同種のサービスなので、Apple Watchが発売されれば同様に話題になるでしょう。まぁ、そのあたりのサービスのMicrosoft版というわけです。
米国のPHR/EHRサービスの動向についてはこちらのレポートが参考になります。

米国における医療分野のIT導入に係る動向 - IPA ニューヨークだより 2012 年 5 月
https://www.ipa.go.jp/files/000001951.pdf (PDF)

ではその中でHealthVaultを使うメリットはというと、マルチプラットフォーム・マルチデバイス対応と、既にサービスを長期運営していることなどに加えて医療機関などへの積極的なアプローチを行っている点でしょう。Google Healthが利用していたCCDフォーマットに積極的に対応するなど、PHRサービスについて調べていると日本でも米国でのサービス例として故Google HealthとHealthVaultが2大サービスとして紹介され、来るべきヘルスケアや電子カルテなどとの乗り入れの課題として解説されていることが多いです。公共機関やエンタープライズ系でのMicrosoftの手堅さが効いてきている感じでしょうか、今後は魑魅魍魎が跋扈するような(失礼)日本の医療IT業界でどれぐらいこの手のサービスが利用されるようになるか、このジャンルでどれぐらいAppleが伸してくるか、といった辺り興味は尽きないところですが、はてさて、という感じ。

前置きが長くなってみましたが、HealthVault使ってみましょう。
...といっても、使い方は超簡単です。

そんだけ。
それでは以下はスクリーンショットで...。
まずは、 https://www.healthvault.com/jp/ja へアクセス。
右上の「サインアップまたはサインインサインイン」をクリック

おなじみのMicrosoftアカウントのログインが面が出るのでログイン。
アカウントが無ければ作成しましょう。

次は、既存のアカウント情報の確認と使用許諾ですね。
「あなたの情報の編集」で登録情報を事前に修正できます。ニュースレターの登録はお好みで。使用許諾のチェックボタンをチェックして「同意する」で登録完了。

ホーム画面が出れば、後はデバイスを紐づけたり、データをどかどかと登録していくだけです。

どうでもいいけど、ログイン後のアドレスが.co.ukなのはなぜなのか...?
試しに、血圧・心拍のデータをExcelからインポートしてみましょう。
最寄りの処方箋薬局に無料の血圧計がありまして、わりと行くたびに血圧・心拍を測定して、結果をスキャンしてEvernoteに突っ込んであったので、これをExcelに起こします。


なんかスペルミスしてるのがお恥ずかしい…。結果を紛失したり用紙切れの時もあるので隙間空いてます。
で、HealthVaultの血圧欄で、ツールバーから「インポート」を選択。

インポート画面が出るので指示に従って、今回はローカルのxlsxファイルを選択してインポート。




さらに、データの列とデータ形式を選択して一致させます。この辺りの作り込みはさすがですね。



というわけで、血圧と心拍数のデータがインポートされました。

当然、グラフも出ますよ。

医療検査結果を入力するフォームはこんな感じ。

緊急時プロファイルを作成すると、こういう感じです。

ざっと駆け足で見てみましたが、いかがでしょうか? 実際入力してみて、予想以上にしっかりできていると思いました。イメージ的には医療版SharePointという感じでしょうか?

それから、HealthVaultの魅力の一つ、マルチプラットフォーム・マルチサービス・マルチデバイス対応ですが、まぁiPhone/iPad, Android, Windows Phone, Windows対応は当然として(大事なデータを預けるだけにプラットフォームに縛られないのって重要ですよね?)、サードパーティ製のFitbitやWithingsなど、対応デバイスの量が半端でないです。また、ヘルスケア系のアプリとの連携などにも対応しているようです。
追記: Withingsの体組織計WS-50を実際に購入して試してみたのですが、HealthVault側で「申し訳ありませんが、お住まいの地域では Withings はサポートされていません。」表示となり、接続できませんでした。残念。
https://account.healthvault.co.uk/jp/ja-JP/Directory



日本のメーカーだとOMRONが一部対応しているようですが、今後TANITA等にも頑張って欲しいですね...。

Windows用には、HealthVault Connection Centerというデバイス接続アプリも用意されています。
https://www.healthvault.com/jp/ja/connection-center
開発者向けSDKもありますヨ。
http://msdn.microsoft.com/healthvault

個人的に、こういうデータを埋めてくと結果が得られる系は大好きなので、黙々と入力してしまいそうでヤバい感じですね。時間をみて、過去の健康診断記録なども入力してみたいと思います。検査結果を生データでもらったり、OCRでできればなぁ...。
というわけで、駆け足で紹介してみましたが、Microsoft HealthVault、いかがでしょうか? ちょっと使えそう、という気がしてきませんか? そして、何気に日本語化されていて、今すぐ使えます。まぁ、データを入力してみるかはともかく、Microsoftアカウントをお持ちなら、とりあえず登録してみて、中をぶらぶら見てみると面白いのではないでしょうか?
日本の医療機関も早期にこの手のPHRサービス対応を進めてほしいですね!!

Microsoft Band is 何?


まぁ、数か月前からごく一部で微妙に話題になっていたMicrosoftのSmart WatchというかFitness Band、Microsoft Bandが発表されました。
まずは、とりあえず動画を見よう。

公式ページはこちら:
http://www.microsoft.com/microsoft-band/en-us
俺は買うぜ、今すぐオンラインでポチるぜ、という方はこちら(US限定):
http://www.microsoftstore.com/store/msusa/en_US/pdp/productID.308308800#buy-product
基本的には、シンプルなFitbit系のウェアラブルフィットネスバンドです。横向き液晶が付いてGalaxy Gear Fitに近いイメージですね。
で、Android / iPhone / Windows Phoneに対応。

主な仕様:
サイズ: 19mm x 8.7mm 60g
表示: TFTフルカラー液晶
プロセッサ: ARM Cortex M4
バッテリー駆動時間: 約48時間
センサー: 心拍、三軸加速度・ジャイロ、GPS、照度、皮膚体温、紫外線、マイク
(Optical heart rate sensor, 3-axis accelerometer/gyro, GPS, Ambient light sensor, Skin temperature sensor, UV sensor)
その他の機能: Bluetooth 4.0 LE、バイブレーション、防塵防滴、物理ボタンx2

で、主な特徴は、約2日のバッテリー駆動時間、フィットネス・ワークアウト、心拍の記録や睡眠サイクルの監視などはもちろん。GPSもビルトインでオフライン記録可、UVや体温センサーも付くようです。


電話の着信、E-Mail、SMS、カレンダーの表示に加えて、Windows PhoneならCortanaの音声入力もBand経由で利用可能。





充電は接触型の専用ケーブルです。

サイズはS/M/L。それぞれ手首の高さが39mm/41mm/49mmまで。
Find the right Microsoft Band size
http://www.microsoft.com/microsoft-band/en-us/sizing

...と、ざっと駆け足で公開された情報を紹介してみました。
正直、最後発でただのフィットネスバンド出しても今更だし、MSがやる意味 とは?と思っていたのですが、GPSやら心拍やらUV、体温までてんこ盛りにしてきてコンパクトかつ2日間駆動、そしてCortana対応というのは、なかなかのフルスペックですね。Android WearApple Watchのようなアプリプラットフォームとなる部分を切り捨てている分だけ割り切った良さがあると思います。3プラットフォーム対応ですし、Galaxy Gear FitやFitbit Surgeあたりのハイスペックフィットネスバンドを検討していた方々には結構ど真ん中、かもしれません。

Lumia 930のあれこれ


新しい端末になりました。Lumia 820 → Lumia 930への移行です。
まぁ、あれでそれなので、Windows Phoneは使ったことがある人向けに手短なまとめだけ。

930にした理由:

  • 諸々あって昨年、Lumia 1020を買うタイミングを逃した。
  • なので、できれば1030待ちをしてそちらに換えたかったが今の所当面出そうな気配がない。
  • 830には期待していたが、薄くて軽いのはいいモノのの、見た目と裏腹にカメラのスペックが930以下だったり基本普及機なスペックなので見送り。
    • とりあえずWP8.1の最新端末で、スペックよりも有機ELではなくIPS液晶でより軽い端末が欲しければ830でいいのではないか、と(ただし対応バンド(何の?)は要注意)。
  • 当面はまだ930がWPのハイエンドになりそう。
  • 820を買ったのが2年弱前、当初は半年もせずに日本でWP機が発売されると思っていたのに結局フルに使うことに…。
    • 正直外見もバッテリーもヘタって来た。
    • 820の初期不良症状として、インカメラと液晶内に塵がどんどん入って曇ってきた。
    • とにかくストレージが足りない。
      • WP8.1からSDカードにアプリ導入可能になったものの、それでも足りないメインストレージ8GB。
  • ぼちぼ930の価格も落ち着いてきたことから購入することに。

820→930でのポイント:

  • 外装・ハードウェア
    • Wireless Charging Shell付の820比で、でかい・重い。
    • スペック上は同じぐらいだが、一回り長くなって角が立つ感じ。
    • メタルフレームなので落下時のことを考えるとカバーしたくなり、さらに一回り大きく。
    • ただし、角が立っていて重いのでうっかり落とす率は低そう。
    • 画面が広いのは率直にうれしい。
  • 環境設定
    • Windows Phone 8.0から初期設定時にWiFiでのバックアップリストアが可能になったため、820の諸設定はそのまま引き継げた
      • ライブタイルの配列や設定は引き継がれる(ただし820の2列から3列になるので左に寄っている)
      • 初回起動後に自動的にインストール済アプリが順次ダウンロードされていく
      • アプリ内設定情報の引き継ぎはアプリ毎にまちまち。モダンでしっかりしたアプリはきっちり引き継がれる。
      • 端末名まで引き継がれるので、変更した場合はPCに繋いでWPアプリから変更。
  • 基本性能
    • 基本同じWindows Phone 8.1なのでソフトウェアや使い勝手は大きく変わらない
    • 動作は多少キビキビしてるが劇的ではない。ストレスが純減してる感じか?
    • バッテリー駆動時間は820と変わらないかちょっと良いぐらい。
      • 負荷をかけると本体下部がほんのり暖かくなる。
    • 感度(何の?)は820より一回りいい気がする。
      • 今までだとぎりぎり入ったり入らなかったりした(何が?)トイレの個室で安定して入るようになったりしている。
      • 地下鉄でも(何が?)前より安定している気がする。
  • カメラ
    • カメラの起動速度やAFは気持ち早くなったかなぐらい。
    • 撮影後の画像のズームで倍以上寄れるようになった感じ。
    • 光学手ぶれ補正(OIS)が結構効いてる感があり、手ぶれ写真が減ったと思う。
    • 高感度化で暗所性能もだいぶ上がった感じがする。
    • 色味とかはまぁNokiaテイストで変わらず。
  • その他
    • とりあえず購入後に更新をかけCyan Updateが入った状態で使用中。
      • 8.1 Update 1も来たけどDenim Updateはまだ。
    • インターネット共有は言語・地域を英語(US)のみにしたら有効化できた(韓国語キーボード トリックも試したが、入れただけでは有効化できず)。

アクセサリ等:

  • Lumia Iconと930は形状的には全く一緒なのでアクセサリも基本共通
  • Lumia 930は曲面ガラスで横サイドからなだらかに中央部が膨らんでいる形状
    • 一般的な硬質系のフィルムやガラスは四隅までぴっちり張れない
      • 製品としてはあるが、左右・上下端に隙間ができる製品がほとんど

    • なので、ぴっちりぴったりのフィルムを探すとウェットタイプの軟質フィルムになる
    • とりあえず、入手性がいい所でSKINOMIのNokia Lumia Icon Screen Protector + Full Body Skin Protectorを手配
      • 一週間ほどで到着。
      • 初めての液張りだったので、なかなかうまくいかなかったがなんとか張れた。
      • 多少張りムラが残っても一晩置くと液がぬけてぴったりする。ただし、ムラの跡が残る。
      • 若干ゴムっぽい手触りだけど、指の滑りそのものはわるくないのでとりあえず当面はこれで行くことにする。
      • ケースも届いたので裏面に張るのは止めた。
  • ケースは2個注文してみた。
    • VSTN Nokia Lumia 930 ultra-thin PC Case Cover with fee screen protector (Blue)
    • Pudini Nokia Lumia 930 Frosted Anti Finger Print Case
    • 後者が先にきて、外観も気にいったのでこちらを使うことに。
    • ちなみに、930/Icon対応ケースが国内のオンラインショップで在庫有りになってたりするが、信用しないこと。納期2週間弱ってところ。
  • Qi充電
    • 930は標準でQiのワイヤレス充電対応。
    • ケースを付けた状態でmaxellのWP-PD10.BKで充電問題なし。
    • Qi充電中の過熱は820より少ない気がする。
  • Nokia Treasure Tag(黒)
    • ついでにexpansysで買った。
    • アプリを入れてからペアリングすればアプリに表示される。
    • 端末と離れると振動して音が鳴り、端末側にもアラートが出る。
    • 機能的にはそれだけ。
  • たまたまお蔵入りしていたBLE対応のLogitecのぶるタグ(LBT-VRU01)があったので試してみた
    • ほぼTreasure Tagと同様にTreasure Tagアプリで使える。
    • ぶるタグのボタンを押すと、端末が派手な音で鳴動する。これはTreasure Tagではできないようだ。
    • その他のぶるタグの機能は使え無い(たぶんアプリ側の実装の問題)。

総評:

  • でかい・重い・広い・速い。
  • ストレージがいっぱいあって幸せ。
  • 感度(何の?)がよくなって一回り快適に。
  • カメラ性能は概ね期待通り。
  • とりあえず最新・最強感。
  • WP9.1ぐらいまでは使えるといいね。
  • しかし1030(か何か)が出て、そちらがいい感じなら(以下略)。

...という感じです。

Logitec Bluetooth 4.0対応 BLEタグ ブラック LBT-MPVRU01BK

Logitec Bluetooth 4.0対応 BLEタグ ブラック LBT-MPVRU01BK

CoreTweetでWebAuthenticationBrokerを利用したUniversal Appを作る

以前、

AsyncOAuthとWebAuthenticationBrokerで作るuniversal App用Twitter APIラッパークラス - Neutral Scent
http://d.hatena.ne.jp/kaorun/20140518/1400392292

というエントリーを書きましたが、最近流行りの.NET用TwitterライブラリCoreTweetでも同様にWebAuthenticationBrokerを利用することが可能です。
WebAuthenticationBrokerを利用することによって、WebViewコントロールを張ってPINをコピペして...、などという煩雑な実装を自前でやる必要が無くなり、勝手にTwitterの認証ページを表示して、認証後にAccessTokenを取得し、APIを叩ける状態まで持っていくことができます。
基本的にCoreTweetでWebAuthenticationBrokerを使う場合のポイントは以下の2点:

  • AutorizeAsync()の第3引数に任意のコールバックURLを入れる(既定の"OOB"だとPIN認証になってしまう)
  • GetTokensAsync()の引数として、PINの代わりにVerifierを入れてやる

少々雑ですが、前回と同様のコードを一応張っておきます。

public class SimpleCoreTweetHandler
{
    // CoreTweet/CoreTweet
    // https://github.com/CoreTweet/CoreTweet
        
    internal const string API_CONSUMER_TOKEN = "";
    internal const string API_CONSUMER_SECRET = "";
    internal const string API_CONSUMER_CALLBACK_URL = "";

    public event EventHandler Authenticated; 
    public OAuth.OAuthSession Session { get; private set; }
    public Tokens Tokens { get; private set; }

    public SimpleCoreTweetHandler()
    {
    }
        
    public async Task Auth()
    {
        Session = await OAuth.AuthorizeAsync(API_CONSUMER_TOKEN, API_CONSUMER_SECRET, API_CONSUMER_CALLBACK_URL);

        var uriAuthorize = Session.AuthorizeUri;
        var uriCallback = new Uri(API_CONSUMER_CALLBACK_URL);
#if WINDOWS_PHONE_APP
        WebAuthenticationBroker.AuthenticateAndContinue(uriAuthorize, uriCallback, null, WebAuthenticationOptions.None);
#else // !WINDOWS_PHONE_APP
        var webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, uriAuthorize, uriCallback);
        if (webAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success)
        {
            Debug.WriteLine(webAuthenticationResult.ResponseData.ToString());
            await GetAccessToken(webAuthenticationResult.ResponseData.ToString());
        }
        else if (webAuthenticationResult.ResponseStatus == WebAuthenticationStatus.ErrorHttp)
        {
            MessageDialog ErrMsg = new MessageDialog(string.Format("HTTP Error returned by AuthenticateAsync() : " + webAuthenticationResult.ResponseErrorDetail.ToString()), "Sorry");
            await ErrMsg.ShowAsync();
        }
        else
        {
            MessageDialog ErrMsg = new MessageDialog(string.Format("Error returned by AuthenticateAsync() : " + webAuthenticationResult.ResponseStatus.ToString()), "Sorry");
            await ErrMsg.ShowAsync();
        }
#endif // !WINDOWS_PHONE_APP
    }

#if WINDOWS_PHONE_APP
    //Windows Phone Web authentication broker sample in C#, C++, JavaScript for Visual Studio 2013
    //http://code.msdn.microsoft.com/wpapps/Web-Authentication-d0485122
    //How to continue your Windows Phone Store app after calling an AndContinue method (Windows)
    //http://msdn.microsoft.com/en-us/library/dn631755.aspx
    //How to Use the WebAuthenticationBroker for oAuth in a Windows Phone Runtime WP8.1 App | .NET Zone
    //http://dotnet.dzone.com/articles/how-use
    public async void ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args)
    {
        WebAuthenticationResult result = args.WebAuthenticationResult;

        if (result.ResponseStatus == WebAuthenticationStatus.Success)
        {
            await GetAccessToken(result.ResponseData.ToString());
        }
        else if (result.ResponseStatus == WebAuthenticationStatus.ErrorHttp)
        {
            MessageDialog ErrMsg = new MessageDialog(string.Format("There was an error connecting to Twitter: \n {0}", result.ResponseErrorDetail.ToString()), "Sorry");
            await ErrMsg.ShowAsync();
        }
        else
        {
            MessageDialog ErrMsg = new MessageDialog(string.Format("Error returned: \n{0}", result.ResponseStatus.ToString()), "Sorry");
            await ErrMsg.ShowAsync();
        }
    }
#endif // WINDOWS_PHONE_APP

    private async Task GetAccessToken(string webAuthResultResponseData)
    {
        string responseData = webAuthResultResponseData.Substring(webAuthResultResponseData.IndexOf("oauth_token"));
        var oauthVerifier = responseData
            .Split('&')
            .Where(kv => kv.ToLower().StartsWith("oauth_verifier="))
            .Select(kv => kv.Split('=')[1])
            .FirstOrDefault();
        Tokens = await Session.GetTokensAsync(oauthVerifier);

        if (Authenticated != null)
            Authenticated(this, new EventArgs());
    }

    internal async Task Tweet(string tweets)
    {
        await Tokens.Statuses.UpdateAsync(status => tweets);
    }
}

Windows Phone版では、認証を終わらせるために、アプリが再アクティブ化されるため、App.xaml.csに以下のようなコードを追加する必要があります。(ViewModel.TwitterHandler〜は個々の実装に合わせて変更)

    public sealed partial class App : Application
    {
        protected override void OnActivated(IActivatedEventArgs args)
        {
            base.OnActivated(args);
#if WINDOWS_PHONE_APP
            if (args is WebAuthenticationBrokerContinuationEventArgs)
                ViewModel.SimpleCoreTweetHandler.ContinueWebAuthentication(args as WebAuthenticationBrokerContinuationEventArgs);
#endif // WINDOWS_PHONE_APP
        }
    }

SimpleCoreTweetHandlerのインスタンスを(↑の場合ならViewModel等に)作成してからAuth()を呼んでやり、認証が終わったらCoreTweetでAPIを叩いていくだけです。

Windows Phone 8 とりあえず入れておきたいオススメ定番アプリ25選 (2014年夏)

と、いうわけで、Lumia 930もぼちぼち発売となり、それ以外にも先日のde:codeで開発用端末をいただいた方々も少なからずおられるでしょうし、Windows Phone手に入れたら、今ならとりあえずこの辺は入れておこう、というアプリを駆け足で紹介。
正直、珍しいとか、WPすげー、って感激する感じではないかもしれませんが、地味に実用的ですWindows Phoneというラインナップ。

追記(2015/06/23):
既に提供が終了しているアプリ等もあるので、以下の記事も合わせてご覧ください。
今だから入れたい! おすすめ Windows Phoneアプリ (2015夏) - Neutral Scent
http://d.hatena.ne.jp/kaorun/20150618/1434635071


実用系ツール:
まず、各種公式アプリは自分で探せばよいと思うので、実用系でこれは、というアプリから。

SendToWP7
PCのブラウザやデスクトップからURL等をWPへさくっと転送できる小ツール。とりあえずまず最初に入れておきたい。
PCの設定などは公式ページで。
Nextgen Reader
定番RSS(Feedly)リーダー。
Krile for WP
WPでTwitterクライアントと言えばKrileというぐらいの定番。
Amelloides
API制限がかかるぐらいのTwitter廃人ならこちらか、というヘビーTwitterer向けクライアント。動作も無駄がなく軽い。
4th & Mayor
Foursquareクライアント。4sq公式と比べてチェックインタイルなどがWPらしい機能とUIが素敵。
gMaps
標準の地図アプリHere Mapsの日本地図が微妙すぎるのでGoogle Mapsクライアント。
Bing 翻訳
カメラを使ったAR認識や音声認識なども可能な高性能多国語翻訳アプリ。
なな字引
諸事情で日本語単語登録できないWPのための簡易辞書として。
CasualTimer
いわゆるラーメンタイマー的な、意外とありそうでないキッチンタイマーライクのシンプルなUIのタイマー。

ライブタイル活用情報系アプリ:
Windows Phoneと言えばライブタイルでしょうというわけで、タイルを有効に使ったアプリ。

降水にゃうきゃすと
いわゆるアメダス系ですね。
WeatherJP
お天気タイルの定番。日本製なので予報精度もわりと安心。
タイルカレンダー
カレンダーをタイルでウィジェット風に(祝祭日対応)。カレンダー系はもっと凝ったアプリも色々出ているのでニーズに応じて...。
タイルに今いる住所が出てくるアプリ
超地味なようで意外と便利なんですよ。
リコリス
お気に入りの作者やシリーズのコミックの新着をタイルに。
myBattery
バッテリー状態をライブタイルに出しておくだけでも意外と便利です。

ロックスクリーンアプリ:
Windows Phone 8からのお楽しみ、ロックスクリーンアプリの定番はこのあたりでしょうか。

AccuWeather - Weather for Life
日本語のロック画面で一番相性がいいお天気アプリ。タイルとしてもいい感じ。
NASA Image of the Day
おなじみAPOD(Astronomy Picture Of the Day)のロック画面アプリ。
Live Lock Screen BETA
Windows Phone 8.1用に遅れてリリースされたアクティブロック画面のβ版。でも今の所実用性は微妙。

ゲーム:
Windows Phoneならではのゲームをいくつか...。

Implode!
Microsoft Studio謹製の爆破シミュレーション、地味に1ステージずつ進めてくのがいい感じです。結構ムズイステージもあり。
Metrogue
名前そのまま、MetroデザインのRogueRPGです。タッチ操作でタイル化されたアイコンをガシガシぶつけてく感じ。レベル感もちょうどよくさくさく進めつつ歯ごたえもあり。

Microsoft公式ツール:
Microsoft Officeチームなどの公式便利アプリもあれこれと。

Office Lens
Officeチーム公式の画像読み込みアプリ。画像処理で台形補正などしてOneNoteに直接Upload。
Office Remote
WPをPowerPoint/Word/Excelのリモコンに。いわゆるプレゼンターツール的な。公式だけにサムネールで移動など凝ったことも。
Authenticator
Microsoftアカウント(旧称Live ID)の二段階認証用トークン生成アプリ。ちなみに、FacebookGoogleの二段階認証用コードジェネレーターとしても利用できます。


最後に拙作を紹介...。

食べログStreetWalker
食べログでブックマークしたお店をいつでも見たかったんですよ。
NatehaR.Express
WP8.1の共有コントラクトを使って、NextgenReaderやIEなどから直接はてブに登録。

あと、とりあえず、ブラウザで表示してるページのピン止めは基本です。通常、現在表示中のページの上半分ぐらいがサムネールになってタイル化できます。
というわけで、自分で良く使っているアプリの中からパッと思いつくモノを駆け足でざっと紹介してみました。他にも色々あると思いますが、これぐらい入れるととりあえずはだいぶ実用的になるか、と。
ただ、特に日本のWPクラスタの開発者は唯一の端末IS12Tの登場以後、端末供給を断たれドメスティックなアプリを売る市場も無く、長く虐げられ続けてきた歴史があり、メンテが滞っているアプリも多いです。その点はお察しください、ということで...。
他にも思いついたら追記します。あれ抜けてるやろ、というツッコみ歓迎。

続編:
今だから入れたい! おすすめ Windows Phoneアプリ (2015夏) - Neutral Scent
http://d.hatena.ne.jp/kaorun/20150618/1434635071