仕事
個人活動
http://tanaka733.net
http://www.buildinsider.net/web/bigquery/
2
フル.NET Framework の力を!
RunSpaceでPowerShell呼び出し (System.Management.Automation.dll)
Gitコマンドの呼び出しとか (libgit2sharp)
配布の容易さ
MSDeploy や DSC、ClickOnce など
安心と信頼のデスクトップアプリ
デスクトップは不滅
安定した技術基盤
4
投資され続けるWPF
5
6
7
DEMO
VS2015のWPF関連の新機能
8
二つのきっかけ 9
内製デプロイツール
機能概要
Windows Serverで動作して、アプリのリリースを行う
RunSpaceを利用し、PowerShellコマンドを実行
作り直しの機運
ViewModelが肥大化した上に複雑化して機能追加がつらい
デプロイの仕組みを変えるのでいいタイミングではあった
VS2015RC への移行(生贄)
ついでに C# 6.0にあげよう
10
いい感じにGitリポジトリ一覧を管理したい
VS統合/GitHub for WindowsはGitが隠ぺいされすぎててちょっと
A社製ツールはリポジトリが多いと扱いづらい
GitコマンドはCLIでいいので、
リポジトリの情報をわかりやすく表示したい
11
ないなら作ればいいじゃない
作り直し事例で考えるWPFアプリのクラス構造
新しいアプリで考えるライブラリの利用事例
Livet
C# 6.0 + ReactiveProperty
13
おさらい (WPFとMVVM)
View
XAMLとコードビハインド
ViewModel (VM)
Viewのデータストア(ViewにBindingする値)
Viewのためのプロパティやコマンドを持つ
Model(M)
VとVM以外。
15
ライブラリの見直し
旧アプリ
MVVMLight
新アプリ
Livet
ReactiveProperty
16
MVVMLightで感じた問題点
単機能ツールのはずが…
画面は1つのままだけど機能がリッチに
もっと強力な支援がほしい
ModelとViewModelの連携
Modelの変更通知をViewModelで受け取る支援がない
結果、ViewModelに書いてしまって肥大化…
17
18
Model と ViewModel の境目
19
App.dll App.Core.dll
App.Cmdlet.dll
MV VM
何に困るのか?
ModelをPlainなクラスライブラリ内にある
変更通知しづらい
ViewModelが肥大化することに…
コマンドから叩くのにUIを考慮したクラス?
VMとのIFとなるMはUIを考慮する
CmdletとのIFも…?
20
MVVM再び
21
V VM M
Model と ViewModel の境目
22
App.dll App.Core.dll
App.Cmdlet.dll
M
V VM
Model と ViewModel の境目
23
App.dll App.Core.dll
App.Cmdlet.dll
M
V VM
VMとの
IF
共通
ロジック
Livetにしよう
WPFに特化したMVVM支援ライブラリ
「WPFのための」ライブラリ
最も多機能※なXAMLプラットフォームに合わせている
ModelとViewModelの連携
Modelの変更通知をViewModelで受け取る支援がない
結果、ViewModelに書くことになって肥大化…
※ UWPのXAMLはXAMLと異なる機能で強化されている
24
25
煩雑になるViewModel
26
Commandの実行可否の状態管理
プロパティ変更を適切にハンドルしないと
プロパティ間の連携
Modelの変更通知をViewModelで受け取る支援がない
結果、ViewModelに書くことになって肥大化…
Modelとのやりとり
自身の変更をModelに通知
Modelの変更を自身に反映
27
ReactivePropertyとは
Rxベース = すべてが IO<T> になる
Vのイベント、Mからの変更通知をIO<T>でつなぐ
ModelとViewModelを楽に定義
Modelプロパティを1行でRP<T> なVMのプロパティに
宣言的なVMのプロパティの定義
プロパティ間のつながりをRxを使って宣言的に記述
28
新しいアプリで考える
ライブラリの実用事例
MVVM再び
30
V VM M
Livet + ReactivePropty 概観
31
V VM M
Livetのおすすめ資料
Livetインストーラーのサンプルプロジェクト
まずはサンプルコードを見てみる
GitHubでLivetのクラス名入れて検索!
意外とヒットして、使い方のサンプルになる
32
ReactivePropertyのおすすめ資料
MVVMパターンのシンプルなサンプル
(Livet + ReactiveProperty)
まずはサンプルコードを見てみる
ReactiveProperty解説
新機能の説明とか
未来のプログラミング技術をUnityで -UniRx-
Unity向けだけど、RPの解説としてもわかりやすい
33
34
V  VM の流れ
35
<i:EventTrigger EventName="ContentRendered">
<behaviors:LivetCallMethodAction
MethodTarget="{Binding}"
MethodName="Initialize"/>
</i:EventTrigger>
<ListView
ItemsSource="{Binding Repositories}"
SelectedItem="{Binding Selected.Value,
Mode=TwoWay}“/>
public void Initialize()
{
Model.RepositoryMaster
.Load().FireAndForget();
}
public ReadOnlyReactiveCollection<Repository>
Repositories { get; }
public ReactiveProperty<Repository> Selected { get; }
= new ReactiveProperty<Repository>();
Repositories = Model.RepositoryMaster
.Repositories
.ToReadOnlyReactiveCollection(
x => new Repository(x))
.AddTo(CompositeDisposable);
VM  M の流れ
36
public void Initialize()
{
Model.RepositoryMaster
.Load().FireAndForget();
}
public ReadOnlyReactiveCollection<Repository>
Repositories { get; }
public ReactiveProperty<Repository> Selected { get; }
= new ReactiveProperty<Repository>();
Repositories = Model.RepositoryMaster
.Repositories
.ToReadOnlyReactiveCollection(
x => new Repository(x))
.AddTo(CompositeDisposable);
public ObservableCollection<GitRepository>
Repositories { get; }
= new ObservableCollection<GitRepository>();
public async Task Load()
{
var repos = (await source.GetRepositories())
.Select(r =>
new GitRepository(r.Item1, r.Item2));
Repositories.Clear();
foreach (var repo in repos)
{
Repositories.Add(repo);
}
}
(VMとのIFになる)Modelの実装例
NotificationObjectを継承
変更通知するプロパティを実装
VMから操作されるメソッドを実装
void もしくは async Task (実質的な返り値なし)
操作した結果はすべて変更通知プロパティ経由で受け取る
つまり、とてもステートフルなクラス
37
ViewModelの実装例
ViewModelを継承
MessengerとかCompositeDisposableが使える
ViewにBindingするプロパティを実装
ReactiveProperty<T> や ReactiveCollection<T>
Viewが操作する処理をコマンドorメソッドとして実装
void もしくは async Task (実質的な返り値なし)
操作した結果はすべて変更通知プロパティ経由で受け取る
38
Viewの実装例
RP<T>をBindするときは.Value
RPを使う場合のView側の実装はこの程度
LivetだとメソッドをBinding可能
Command定義しなくてもいいよ
Messengerを受け取るアクション
VM  M の通知手段
Buttonクリック  確認ダイアログ  VMのメソッド実行
までをXAML内で完結
39
具体例
いくつか実例を
40
41
<TextBlock Text="{Binding AlertMessage.Value}">
<TextBlock.Visibility>
<Binding Path="HasAlert.Value">
<Binding.Converter>
<converters:VisibilityAndBooleanConverter
ConvertWhenTrue="Visible"
ConvertWhenFalse="Collapsed"/>
</Binding.Converter>
</Binding>
</TextBlock.Visibility>
</TextBlock>
42
<Button Content="危険な処理" IsEnabled="{Binding CanExecute.Value}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<messaging:ConfirmationDialogInteractionMessageAction>
<messaging:DirectInteractionMessage CallbackCommand="{Binding HogeCommand}">
<messaging:ConfirmationMessage Button="OKCancel" Caption="確認"
Text="実行していいですか?" />
</messaging:DirectInteractionMessage>
</messaging:ConfirmationDialogInteractionMessageAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
HogeCommand = CanExecute.ToReactiveCommand<ConfirmationMessage>();
HogeCommand.Where(message => message.Response == true)
.Subscribe(_ =>
{
/* 何か処理*/
})
.AddTo(CompositeDisposable);
43
<Button Content="もっと危険なコマンド" IsEnabled="{Binding CanExecute.Value}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<messaging:TransitionInteractionMessageAction WindowType="{x:Type v:AlertDialogWindow}"
Mode="Modal">
<messaging:DirectInteractionMessage CallbackMethodTarget="{Binding}"
CallbackMethodName="Fuga">
<messaging:TransitionMessage/>
</messaging:DirectInteractionMessage>
</messaging:TransitionInteractionMessageAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
public void Fuga(TransitionMessage message)
{
if (message.Response == true) //ダイアログでOKだったら
{
//何か処理
}
}
まとめ
デスクトップアプリは不滅
デスクトップといえばWPF
M is neither “共通クラス” nor “ビジネスロジック”
MVVMの役割をもう一度考えよう
Mがリッチでないと、VMが肥大化しがち
WPFならLivet便利
ReactivePropertyで宣言的な記述を
45
46
http://amzn.to/1EGFTaN
Visual Studio 2015 における
統合開発環境の進化
Unityを使用した Windows 用の 2D および
3D ゲーム開発ジャンプスタート
MVA コンテンツ

20150530 めとべや東京 Reactive Property + Livetで作るWPFアプリ

Editor's Notes

  • #9 たとえばViewModelをコードで足すと、コンパイルなしにXAMLで補完が聞くようになる XAMLのUIデバッグ=>実際のXAML構造が見れる 診断ツール