[WPF][Silverlight][C#][SignalR]WPFとSilverlightでSignalRクライアントを作成する
[C#]Unity 3.0でも触ってみますか
[C#]Unityで属性を使ってクラス間の依存関係を定義する方法
[C#]Unityでコンテナ登録時とコンテナからのオブジェクト取り出し時に値を設定する
[C#]Unityで配列のインジェクションを行う
[C#]UnityでAOPをしよう
[C#]Unityに型を登録するのが楽になっている件について
[WinRT]Windows ストア アプリでのテンプレート コントロール
方法: LINQ クエリのカスタム メソッドを追加する??
このクソサンプルコードを書いたのは誰だ!レベル。こんなのがMSDNに乗ってるとは…… 方法: LINQ クエリのカスタム メソッドを追加する URL
2013-07-0223:21:53via web
ノイエ先生が突然きれてたので、試してみました。前半がMSDNからのこぴぺ。後半が自分なりになおしてみたやつ。
staticclass LINQExtension { publicstaticdouble Median(this IEnumerable<double> source) { if (source.Count() == 0) { thrownew InvalidOperationException("Cannot compute median for an empty set."); } var sortedList = from number in source orderby number select number; int itemIndex = (int)sortedList.Count() / 2; if (sortedList.Count() % 2 == 0) { // Even number of items.return (sortedList.ElementAt(itemIndex) + sortedList.ElementAt(itemIndex - 1)) / 2; } else { // Odd number of items.return sortedList.ElementAt(itemIndex); } } publicstaticdouble MedianEx(this IEnumerable<double> source) { var items = source.OrderBy(d => d).ToArray(); if (!items.Any()) { thrownew InvalidOperationException("Cannot compute median for an empty set."); } int itemIndex = items.Length / 2; if (items.Length % 2 == 0) { return (items[itemIndex] + items[itemIndex - 1]) / 2; } else { return items[itemIndex]; } } }
Ix-MainをNuGetで参照にくわえて10000個くらいのdoubleの配列に対して1000回くらいループ回してみて時間はかってみました。
var source = EnumerableEx.Generate(0.0, d => d <= 10000.0, d => ++d, d => d); { var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < 1000; i++) { source.Median(); } stopwatch.Stop(); Console.WriteLine("Median: {0}ms", stopwatch.ElapsedMilliseconds); } { var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < 1000; i++) { source.MedianEx(); } stopwatch.Stop(); Console.WriteLine("MedianEx: {0}ms", stopwatch.ElapsedMilliseconds); }
Median: 7290ms MedianEx: 2538ms
ふむ2倍以上遅い。
ということで、何故遅いのかは夜遅いので誰かにパス・・・!
Windows ストア アプリのGridViewのスクロールバーの位置の復元したいよね?
ストアアプリが画面の背後にまわってしまって、中断から終了されてしまったあとに、再度起動されたときに前回終了する前の状態を復元するというのが一般的です。その中で若干厄介なのがGridViewのスクロールバーの位置の復元です。
今回はコードレシピにPrism for Windows Runtimeのプロジェクトテンプレートをベースにスクロールバーの位置の復元サンプルを書いてみました。ポイントはスクロールバーの位置の永続化と、永続化したスクロールバーの位置の読み込み自体はSaveStateとLoadStateメソッドで行うが、実際にスクロールバーの位置を設定するのはページのLoadedイベントで行っている点です。こうすることで、VisualTreeが構築された後のタイミングでスクロールバーの位置を設定しています。(LoadStateメソッド内だと、まだVisualTreeの構築は終わってない感じ)
めとべや東京で発表してきました #めとべや
なんか、久しぶりに凄い緊張した今日この頃。
デモでは見たことないエラーもでるし…!
ということで、死霊(要出典)はSlideShareに置いておきます。
資料の中でも書いてありますがPrismの基本的な機能を書いたサンプルコードはコードレシピに置いてあるので試してみたい方は以下からDLして確認できます。
- Prism for WinRT入門 Hello world
- 標準のストアアプリのテンプレートから、Prismを使ったアプリケーションにするときの手順が書いてあります。
- Prism for WinRT入門 ViewとViewModelの紐づけ
- Prismの機能の1つのViewとViewModelの接続機能について書いてあります。紐づけルールのカスタマイズ方法も。
- Prism for WinRTのValidatableBindableBase
- 入力値の検証機能のためのValidatableBindableBaseの動作を説明してます。あとは、エラーの内容を画面にフィードバックする方法も。
- Prism for WinRTでフライアウトを出したい
- アプリケーションですごく使いたい機能なのに、何故標準機能にない!?と言いたいフライアウト。超簡単にできるので個人的に一押し機能。
- Prism for WinRTでGridViewのスクロール位置を記録する
- これはPrismとは関係ないけど、よくやりたいと思うこと。Prismの機能のページクラスのSaveStateとLoadStateメソッドの利用例です。
ここら辺の基本的な小さなサンプルを読み解けたら次はPrism for Windows Runtimeのサンプル実装を読むといいと思います。いきなり読むには大きすぎるサンプル(多分Prismの機能を全部盛り込むために仕方のないことかもしれないけど)ですが、多分要素要素をおさえたあとなら、割とすんなり読めるはずです。
はてなBlogに引っ越ししました
著書の紹介
はてなブログでは、Amazonさんのアフィリエイトも入れれるみたいなのでテストもかねて。
- 作者:大田一希,和田健司
- 出版社/メーカー:秀和システム
- 発売日: 2012/10
- メディア:単行本
- 購入: 2人 クリック: 52回
- この商品を含むブログ (5件) を見る
Windows ストア アプリをアプリを実際に作りながら学べる本です。前半部分のRSSリーダーを作る章まで担当しました。
このRSSリーダーもうちょい手を入れたら、ストアに出せるんじゃないんだろうか…。セマンティックズームなんかにもきちんと対応してるし、検索やセカンダリタイルと盛りだくさんです。
その他にも、画像処理を行う場合やBing Mapを使うケースも網羅してるので、これをとっかかりにしてストアアプリの開発を行うのにピッタリなように書いてるつもりです。
- 作者:大田一希,和田健司,津守優
- 出版社/メーカー:秀和システム
- 発売日: 2013/03
- メディア:単行本
- この商品を含むブログ (1件) を見る
こちらは、Tips集です。
33個くらい書いた気がします。自分が担当してない箇所のレシピは、読んでて普通に勉強になったりするので献本されたものを大事に持ってたりします。
個人的に一押しなのは、NFCを使ったコードの例です。
WPF4.5入門 その28 「Calendarコントロール」
Calendarコントロールは、名前の通りカレンダーを画面に表示してユーザーに日付を選択してもらうためのコントロールです。Calendarコントロールの代表的な機能を以下に示します。
- 表示内容を1か月、1年、10年に設定できます。
- 複数の日付(単一選択と複数選択の組み合わせ)の選択ができます。
- 選択不可の日付を設定できます。
- Calendarコントロールに表示される日付の範囲を設定します。
- 今日の日付を強調表示できます
基本的な使い方
Calendarコントロールの基本的な使い方を示します。WindowにCalendarコントロールを置くと以下のような表示になります。このように1月ぶんの日付が表示されます。
ここにボタンを置いて、選択日をメッセージボックスで表示してみます。コードは以下のようになります。
<Window x:Class="CalendarSample01.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow"Height="350"Width="525"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><Calendar x:Name="calendar" /><Button Content="Show SelectedDate"Grid.Row="1"Click="Button_Click"/></Grid></Window>
ボタンのクリックイベントハンドラのコードを以下に示します。
privatevoid Button_Click(object sender, RoutedEventArgs e) { MessageBox.Show(this.calendar.SelectedDate.ToString()); }
プログラムを実行して、日付を選択せずにボタンを押すと以下のように空のメッセージボックスが表示されます。SelectedDateプロパティは、DateTime?型のため、未選択時はデータを持ちません。カレンダー内の日付を選択して、ボタンを押すと以下のように選択された日が表示されます。
選択方法のカスタマイズ
Calendarコントロールは、以下のプロパティを設定することで、日付の選択を制御することができます。
プロパティ | 説明 |
---|---|
CalendarSelectionMode SelectionMode { get; set; } | 日付の選択方法を設定します。以下の値から設定できます。MultipleRange:複数の範囲選択ができます,None:何も選択できません。,SingleDate:単一の日付を選択できます。, SingleRange:単一の日付の範囲を選択できます。 |
SelectedDatesCollection SelectedDates { get; } | 選択された日付のコレクションです。AddRangeメソッドを使って指定した日付の範囲を追加することができます。SelectionModeプロパティにMultipleRangeかSingleRangeが設定されているときのみ、AddRangeメソッドが動きます。 |
DateTime? SelectedDate { get; set; } | 単一の選択された日付を取得または設定します。 |
このほかに、BlackoutDatesプロパティを使うことで選択できない日付をカレンダーに設定できます。
プロパティ | 説明 |
---|---|
CalendarBlackoutDatesCollection BlackoutDates { get; } | 選択できない日付のコレクションを返します。AddメソッドでCalendarDateRangeを追加することで、選択できない日付の範囲指定を行います。また、AddDatesInPastメソッドを呼ぶことで過去の日付を選択できないようにします。 |
これらのプロパティを組み合わせることで、柔軟な日付選択の手段をユーザーに提供できます。以下に、今日より前の日付と、翌日から4日間は選択できないようにして、それ以外の日付を複数選択可能にする場合のコード例を示します。
まず、ページのXAMLです。XAMLでは、複数選択が可能なことをSelectionModeプロパティで指定しています。
<Window x:Class="CalendarSample02.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow"Height="350"Width="525"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><Calendar x:Name="calendar"SelectionMode="MultipleRange" /><Button Content="Show SelectedDate"Grid.Row="1"Click="Button_Click"/></Grid></Window>
コードビハインドでは、今日より前の日付の無効化と翌日から4日間を無効化しています。ボタンのクリックイベントではSelectionDatesプロパティから選択された日付を改行区切りの文字列にして表示しています。
using System; using System.Linq; using System.Windows; using System.Windows.Controls; namespace CalendarSample02 { publicpartialclass MainWindow : Window { public MainWindow() { InitializeComponent(); // 今日より前は、選択不可能にする。this.calendar.BlackoutDates.AddDatesInPast(); // 翌日から4日間も選択不可能にするthis.calendar.BlackoutDates.Add( new CalendarDateRange( DateTime.Today.AddDays(1), DateTime.Today.AddDays(4))); } privatevoid Button_Click(object sender, RoutedEventArgs e) { // 選択された日付を連結して表示 var selected = string.Join(Environment.NewLine, this.calendar.SelectedDates.Select(d => d.ToString())); MessageBox.Show(selected); } } }
実行して、何日か日付を選択してボタンをクリックした結果を以下に示します。日付を複数選択できていることと、指定した範囲の日付が選択できないように×印がついています。
表示範囲のカスタマイズ
CalendarコントロールのDisplayDateStartプロパティとDisplayDateEndプロパティを使うことで、カレンダーで選択可能な日付の範囲を指定できます。
プロパティ | 説明 |
DateTime? DisplayDateStart { get; set; } | カレンダーの日付の範囲の最初の日付を取得または設定します。 |
DateTime? DisplayDateEnd { get; se;t } | カレンダーの日付の範囲の最後の日付を取得または設定します。 |
以下にXAMLでDisplayDateStartプロパティとDisplayDateEndプロパティで2013/07/01から2013/07/15までの範囲を設定した場合の例を示します。
<Window x:Class="CalendarSample03.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow"Height="350"Width="525"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><Calendar x:Name="calendar"DisplayDateStart="2013/07/01"DisplayDateEnd="2013/07/15"/><Button Content="Show SelectedDate"Grid.Row="1"Click="Button_Click"/></Grid></Window>
実行すると以下のような結果になります。表示されている日付が指定した範囲に制限されていることが確認できます。
過去記事
- WPF4.5入門 その1 「はじめに」
- WPF4.5入門 その2 「WPFとは」
- WPF4.5入門 その3 「Hello world」
- WPF4.5入門 その4 「Mainメソッドはどこにいった?」
- WPF4.5入門 その5 「全てC#でHello world」
- WPF4.5入門 その6 「WPFを構成するものを考えてみる」
- WPF4.5入門 その7 「XAMLのオブジェクト要素と名前空間」
- WPF4.5入門 その8 「オブジェクト要素のプロパティ」
- WPF4.5入門 その9 「コレクション構文」
- WPF4.5入門 その10 「コンテンツ構文」
- WPF4.5入門 その11 「マークアップ拡張」
- WPF4.5入門 その12 「その他のXAMLの機能」
- WPF4.5入門 その13 「簡単なレイアウトを行うコントロール」
- WPF4.5入門 その14 「レイアウトコントロールのCanvasとStackPanel」
- WPF4.5入門 その15 「レイアウトコントロールのDockPanelとWrapPanel」
- WPF4.5入門 その16 「ViewBoxコントロール」
- WPF4.5入門 その17 「ScrollViewerコントロール」
- WPF4.5入門 その18 「Gridコントロール part 1」
- WPF4.5入門 その19 「Gridコントロール part 2」
- WPF4.5入門 その20 「レイアウトに影響を与えるプロパティ」
- WPF4.5入門 その21 「WPFのコンセプトと重要な機能つまみ食い」
- WPF4.5入門 その22 「Buttonコントロール」
- WPF4.5入門 その23 「DataGridコントロール その1」
- WPF4.5入門 その24 「DataGridコントロール その2」
- WPF4.5入門 その25 「TreeViewコントロール その1」
- WPF4.5入門 その26 「TreeViewコントロール その2」
IsHitTestVisibleで存在感無いやつを作る
WPFのコントロールでIsHitVisibleプロパティをFalseにするとクリックしたときに、存在しない人のようになります。
こいつをうまいこと使うと、見えてる要素なんだけど、操作対象じゃないというようなウォーターマークみたいなものを簡単に作れます。
あと、実用性はないですがTextBoxとかの上に半透明の別のコントロールをかぶせてIsHitTestVisibleをFalseにしておくと、半透明の人を通り越してTextBoxの操作ができたりします。
こんな風にTextBoxに完全にかぶるようにTabControlを置いてIsHitTestVisibleをFalseにしてみます。
<Grid><TextBox HorizontalAlignment="Left"Height="23"Margin="153,120,0,0"TextWrapping="Wrap"Text="TextBox"VerticalAlignment="Top"Width="120"/><TabControl HorizontalAlignment="Left"Height="159"Margin="127,57,0,0"VerticalAlignment="Top"Width="242"Opacity="0.4"IsHitTestVisible="False"><TabItem Header="TabItem"><Grid Background="#FFE5E5E5"/></TabItem><TabItem Header="TabItem"><Grid Background="#FFE5E5E5"/></TabItem></TabControl></Grid>
実行してみるとTabControlをスルーしてTextBoxに入力ができます。
なかなか面白い。
普通のアプリケーションでは、使い道ってあんまりないかもしれませんがコントロールテンプレートをいじるときにウォーターマークをつけるとか、何か特殊な効果をつけたいだとか言うときにちょっと役に立つテクニックです。
WCF RIA Servicesがオープンソースになる・・・!
RIA Services is Getting Open-Sourced
http://jeffhandley.com/archive/2013/07/03/ria-services-is-getting-open-sourced.aspx
ここ最近で一番アツイニュースです!CodePlexにソースもホストされるみたいだし…、消えるにはもったいないと思ってただけに、とってもいいニュース!とりあえず要チェックですね。
Prism for WinRTでRSSリーダー作ってみた
Windows 8 ストア アプリ開発入門の中で作ったRSSリーダーと、ほぼ同じものをPrism for Windows Runtimeを使って実装してみました。
- 作者:大田一希,和田健司
- 出版社/メーカー:秀和システム
- 発売日: 2012/10
- メディア:単行本
- 購入: 2人 クリック: 52回
- この商品を含むブログ (5件) を見る
コードレシピからダウンロードして確認できます。
ささっと作った感じなので、バグってるかもしれないですが、少しでも参考になれば幸いです。
因みに、Model部分は書籍で書いたものをほとんどそのまま再利用しています。ViewModelとViewの部分をPrismに置き換えて作っています。見た目とそれ以外を分離するように心がけていると、移植が楽だなぁと感じた今日この頃でした。
await可能なクラスを作ってみよう
C#の新機能というにはもう古いかもしれないasync/awaitですが…こいつはTask
でも、実際はTask
軽い前提知識
await可能なクラスには以下のメソッドがあること
- T GetAwaiter()
GetAwaiterメソッドの返すクラスには以下のプロパティとメソッドがあること
- bool IsCompleted { get; }
- void OnCompleted(Action continuation)
- T GetResult()
深く知りたいという人はMSDNマガジンの以下の記事をおすすめしておきます。
await可能なクラスを作るための下準備
コンソールアプリケーションにRunというメソッドを作って、そのメソッドをMainメソッドから呼び出します。Runメソッドにはasyncを付けて中でawaitが使えるようにしましょう。Runメソッドの呼び出しのあとには、一応Console.ReadLine()でアプリがストンと落ちないようにしておきます。
using System; namespace ConsoleApplication4 { class Program { staticvoid Main(string[] args) { Run(); Console.ReadLine(); } privatestatic async void Run() { } } }
このRunメソッド内に処理を書いていきます。まずawaitするためのクラスを作ります。クラス名はHello worldらしくHelloWorldAwaitableにしました。GetAwaiterメソッドを作ってHelloWorldAwaiter構造体を返すようにしてます。
class HelloWorldAwaitable { public HelloWorldAwaiter GetAwaiter() { returnnew HelloWorldAwaiter(); } } struct HelloWorldAwaiter { }
さて、Runメソッド内でawaitしてみます。
privatestatic async void Run() { var result = await new HelloWorldAwaitable(); }
この状態でビルドすると以下のようなコンパイルエラーが出ます。
error CS0117: 'ConsoleApplication4.HelloWorldAwaiter' に 'IsCompleted' の定義がありません。
最初に書いたawait可能な条件を満たしてないということですねIsCompletedプロパティを以下のように追加してみました。今回は、常にawait呼び出した直後では処理が終わってないということにしたいのでfalseを返すだけの実装にしてます。
struct HelloWorldAwaiter { publicbool IsCompleted { get { returnfalse; } } }
これでビルドするとコンパイルエラーが以下のように変わります。
error CS4027: 'ConsoleApplication4.HelloWorldAwaiter' does not implement 'System.Runtime.CompilerServices.INotifyCompletion'
INotifyCompletionという馴染みのないインターフェースを実装していないといわれました。
こいつは、OnCompletedメソッドを持ってるだけのシンプルなインターフェースです。確か必須条件の中に、そんなメソッドがありましたね。ということで実装します。*1
struct HelloWorldAwaiter : INotifyCompletion { publicbool IsCompleted { get { returnfalse; } } publicvoid OnCompleted(Action continuation) { } }
この状態でコンパイルをすると、今度は以下のようにコンパイルエラーのメッセージが変わります。
error CS0117: 'ConsoleApplication4.HelloWorldAwaiter' に 'GetResult' の定義がありません。
なんかawaitできるっぽいけど最後に結果をとるのがうまくいってないみたいですね。ということで、GetResultを以下のように実装します。今回は、Hello worldを返すだけにしてます。
struct HelloWorldAwaiter : INotifyCompletion { publicbool IsCompleted { get { returnfalse; } } publicvoid OnCompleted(Action continuation) { } publicstring GetResult() { return"Hello world"; } }
これでコンパイルエラーが消えるのでRunメソッドの中身の続きを書いていきます。awaitした結果を標準出力に出力します。
privatestatic async void Run() { var result = await new HelloWorldAwaitable(); // awaitした結果を出力! Console.WriteLine(result); }
これで実行すると…何も出ません。awaitを呼び出した後の処理を適切に行おうと思ったらHelloWorldAwaiterのOnCompletedメソッドの中身を実装する必要があります。OnCompletedメソッドの引数にわたってきているActionに、awaitした続きの処理が入っているようなイメージなので、こいつを呼び出してやるとOKです。ということで、OnCompletedメソッドの中身は以下のようになります。
struct HelloWorldAwaiter : INotifyCompletion { publicbool IsCompleted { get { returnfalse; } } publicvoid OnCompleted(Action continuation) { // awaitの続きを頼む continuation(); } publicstring GetResult() { return"Hello world"; } }
これでプログラムを実行すると以下のような結果になります!
Hello world
ということでawait可能なクラスを作るHello worldプログラムでした。気になる箇所にブレークポイントをはって、ステップ実行してみると面白いかも?
*1:OnCompletedメソッドがあればいいのかと思ったら、このインターフェース実装してないとコンパイルエラーになった。う~ん
タッチ?マウス?スタイラス?
気になったのでTouchとMouseとStylusイベントの動きを軽く見てみました。軽くというのは時間がないので****Down系イベントだけ拾ってみました。Backgroundを指定したBorderを置いてCheckBoxを3つおく。
<Window x:Class="StylusCheckApp.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow"Height="350"Width="525"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition/></Grid.RowDefinitions><Border BorderBrush="Black"BorderThickness="1"Margin="10"Grid.Row="3"StylusDown="Border_StylusDown"MouseDown="Border_MouseDown"TouchDown="Border_TouchDown"Background="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/><CheckBox x:Name="checkBoxStylus"Content="Handle Stylus"Margin="10"/><CheckBox x:Name="checkBoxMouse"Content="Handle Mouse"Grid.Row="1"Margin="10"/><CheckBox x:Name="checkBoxTouch"Content="Handle Touch"Grid.Row="2"Margin="10"/></Grid></Window>
んで、コードビハインドでデバッグログを吐くだけ。
using System.Diagnostics; using System.Windows; using System.Windows.Input; namespace StylusCheckApp { publicpartialclass MainWindow : Window { public MainWindow() { InitializeComponent(); } privatevoid Border_StylusDown(object sender, StylusDownEventArgs e) { Debug.WriteLine("StylusDown"); e.Handled = this.checkBoxStylus.IsChecked.Value; } privatevoid Border_MouseDown(object sender, MouseButtonEventArgs e) { Debug.WriteLine("MouseDown"); e.Handled = this.checkBoxMouse.IsChecked.Value; } privatevoid Border_TouchDown(object sender, TouchEventArgs e) { Debug.WriteLine("TouchDown"); e.Handled = this.checkBoxTouch.IsChecked.Value; } } }
実行してみる。
マウスクリック MouseDown タッチ StylusDown TouchDown MouseDown スタイラスでツン StylusDown MouseDown
ちょっとびっくりしたのがタッチしても最初のイベントはスタイラス。ほほう…。ではStylusでHandledをTrueにすると…。
マウスクリック MouseDown タッチ StylusDown MouseDown スタイラスでツン StylusDown MouseDown
タッチイベントはスキップされたけどマウスイベントにはいっちゃうのか。んじゃ、タッチイベントだけHandledをTrueにすると…。
マウスクリック MouseDown タッチ StylusDown TouchDown MouseDown スタイラスでツン StylusDown MouseDown
ほう…。
まとめ
****Down系イベントだけを見るとMouseイベントの前にStylus→Touch→Mouseときたらタッチ操作で、Stylus→MouseときたらスタイラスでMouseだけだとマウスということになります。
Preview****系とか、その他もろもろのStylus*****系イベントとかを駆使すると、もっと何かかわるのかもしれないけど、続きは後日の自分か誰か…。
Windows ストア アプリでlocalhostに繋がらない?
Visual Studioとかから実行すろと、自動的にlocalhostへループバックできるような設定が裏で追加されるんですね…知らなかった。ということで、業務アプリとかでデスクトップ側の世界と何かやりとりしたいという要望に応えるためにデスクトップ側にWebサーバー立てて、ストアアプリからlocalhostに対してWeb API呼んだりSignalRでリアルタイム通信だぜ・・・!とか目論んでた場合は、そのままでは死亡です。
試しに以下のコマンドをうってみると、ずらずらずら~~~っと表示されるはずです。
# ループバックを許可するということを許された人のリスト CheckNetIsolation.exe LoopbackExempt -s
localhostへ通信出来てたと思ってたアプリにとどめを刺すというか、他の人のマシンにサイドローディングしたのと同じ状況を再現するには、以下のコマンドをうってざっくりと除外設定を削除します。
# ループバックを許可するということを許された人を削除 CheckNetIsolation.exe LoopbackExempt -c
こうすると、晴れてストアアプリからlocalhostへの接続ができなくなります。
じゃぁどうしよう?という話になるのですが、CheckNetIsolation.exeでループバックを許可するやつをコマンドで明示的に許してやる必要があります。ストアアプリのPackage.appxmanifestのパッケージ化の所にあるパッケージファミリ名を使うのが一番お手軽そうです。
# パッケージファミリ名を指定してループバックを許可するように指定 CheckNetIsolation.exe LoopbackExempt -a -n=パッケージファミリ名
こうしてやると、無事そのアプリでlocalhostにつながるようになります。めでたしめでたし…。サイドローディングでインストールするときに、このコマンドも一緒に叩くようにしておかないといけないくさいな…。めんどくさそう。
さいごに
もっといい方法募集中。