Livet をカスタマイズする(1.0.6.1版 VB.NET用)
以前のエントリからだいぶ日にちが経ち、Livet も 1.0.6.1 と大きくバージョンアップしました。それに伴い仕様も大きく変わり、VB ユーザーには少々使いづらくなったので、以前の改造だけじゃ足りない部分も増えてます。そこで最新バージョンに合わせ、Livet を改造したいと思います。
プロジェクトテンプレートの変更
1.0以降大きく変わったのが、プロジェクトテンプレートです。テンプレートは、以下のフォルダにある Livet_WPF4.x_VB.zip に含まれてるので、これを編集します。
Visual Studio のインストールフォルダ/Common7/IDE/ProjectTemplatesCache/VisualBasic/Windows/1041
なおテンプレートの本体は
Visual Studio のインストールフォルダ/Common7/IDE/ProjectTemplates/VisualBasic/Windows/1041
にありますが、こちらは通常使いませんのでとりあえず放置しときます。ただし VisualStudio のインストーラーで「修復」を実行すると初期化されてしまうので、時間があればこちらも変更しとくのをお勧めします。
Model・ViewModel・View の各VBにネームスペースが追加されてますが、VB の場合、正直不要なのでばっさり削除。さらに Option ステートメントと Imports を追加します。なお空白行やコメントは記事の都合上割愛してますが、実際のファイルではそのまま残してます。
Model.vb
Option Explicit On Option Strict On Imports Livet Friend Class Model Inherits NotificationObject End Class
ViewModel はもっともよく使うので、Imports を大量に追加。プロジェクトで生成する分には Imports を追加しなくてもいいのですが、私の場合、既存のプロジェクトに後から ViewModel を追加することがあるので、ここで ViewModelのテンプレートの仕様を固めてしまい、項目テンプレートにコピーします。
後 1.0以降から追加されたのが、ViewModel の Dispose。これは使う場面が多いので、テンプレートに雛形を記述しときます。
MainWindowViewModel.vb
Option Explicit On Option Strict On Imports System.Collections.ObjectModel Imports Livet Imports Livet.Commands Imports Livet.EventListeners Imports Livet.Messaging Imports Livet.Messaging.Windows Public Class MainWindowViewModel Inherits ViewModel ' ・・・・・・ Public Sub Initialize() End Sub #Region "Dispose Support" Protected Overrides Sub Dispose(disposing As Boolean) MyBase.Dispose(disposing) If (disposing) Then End If End Sub #End Region End Class
View も以下のように変更します。MainWindow.xaml と MainWindow.xaml.vb の二つを編集します。
Option Explicit On Option Strict On Imports Livet Class MainWindow End Class
MainWindow.xaml
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" xmlns:l="http://schemas.livet-mvvm.net/2011/wpf" xmlns:local="clr-namespace:$safeprojectname$" Title="MainWindow" Height="350" Width="525"> <Window.DataContext> <local:MainWindowViewModel/> </Window.DataContext> <i:Interaction.Triggers> <!--WindowのContentRenderedイベントのタイミングでViewModelのInitializeメソッドが呼ばれます--> <i:EventTrigger EventName="ContentRendered"> <l:LivetCallMethodAction MethodTarget="{Binding}" MethodName="Initialize"/> </i:EventTrigger> <!--Windowが閉じたタイミングでViewModelのDisposeメソッドが呼ばれます--> <i:EventTrigger EventName="Closed"> <l:DataContextDisposeAction/> </i:EventTrigger> <!--WindowのCloseキャンセル処理に対応する場合は、WindowCloseCancelBehaviorの使用を検討してください--> </i:Interaction.Triggers> <Grid> </Grid> </Window>
項目テンプレートを改造
次は項目テンプレートを編集します。項目テンプレートは以下のフォルダにインストールされています。
Visual Studio 2010 のインストールフォルダ/Common7/IDE/ItemTemplatesCache/VisualBasic/WPF/1041
ここに配置されてる ZIP ファイルを展開し編集します。ZIP ファイルと編集するファイルの関係は以下のとおり。メッセージのテンプレートはまだ使い方判ってないので、今回は編集対象から除外しました。
ZIP | 編集対象のファイル |
LivetModel_VB.zip | Model.vb |
LivetViewModel_VB.zip | ViewModel.vb |
LivetWindow_VB.zip | Window.xaml |
LivetWindow_VB.zip | Window.xaml.vb |
この四つのファイルを以下のように変更します。
Model.vb
Option Explicit On Option Strict On Imports Livet Friend Class $safeitemname$ Inherits NotificationObject 'NotificationObjectはプロパティ変更通知の仕組みを実装したオブジェクトです。 End Class
ViewModel.vb
Option Explicit On Option Strict On Imports System.Collections.ObjectModel Imports Livet Imports Livet.Commands Imports Livet.EventListeners Imports Livet.Messaging Imports Livet.Messaging.Windows Public Class $safeitemname$ Inherits ViewModel ' ・・・・・・ Public Sub Initialize() End Sub #Region "Dispose Support" Protected Overrides Sub Dispose(disposing As Boolean) MyBase.Dispose(disposing) If (disposing) Then End If End Sub #End Region End Class
Option Explicit On Option Strict On Imports Livet Class $safeitemname$ End Class
Window.xaml
<Window x:Class="$safeitemname$" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" xmlns:l="http://schemas.livet-mvvm.net/2011/wpf" xmlns:local="clr-namespace:$projectrootnamespace$" Title="$safeitemname$" Height="350" Width="525"> <Window.DataContext> <local:$safeitemname$ViewModel/> </Window.DataContext> <i:Interaction.Triggers> <!--WindowのContentRenderedイベントのタイミングでViewModelのInitializeメソッドが呼ばれます--> <i:EventTrigger EventName="ContentRendered"> <l:LivetCallMethodAction MethodTarget="{Binding}" MethodName="Initialize"/> </i:EventTrigger> <!--Windowが閉じたタイミングでViewModelのDisposeメソッドが呼ばれます--> <i:EventTrigger EventName="Closed"> <l:DataContextDisposeAction/> </i:EventTrigger> <!--WindowのCloseキャンセル処理に対応する場合は、WindowCloseCancelBehaviorの使用を検討してください--> </i:Interaction.Triggers> <Grid> </Grid> </Window>
変更通知プロパティのスニペットを改造
Livet をインストールするとスニペットは
Visual Studio 2010 のインストールフォルダ/VB(C# ならC#フォルダ)/Snippets/1041/application
に配置されます。VB の場合、Livet用通知プロパティのスニペットは LivetProperty_VB.snippet。これをエディタで開いて、XMLコメントを加えます。ついでにデバッグ時にゲッターをスルーするよう DebuggerNonUserCode 属性を追加。また value の比較ですが、VB の等号演算子では参照型の比較ができないため、Object.Equals を使います。これなら値型はもちろん、文字列や参照型も比較してもらえます。Object.Equals いいね!d(・∀・)グッ!! 後はプロパティの説明や先頭の改行も考慮するとこうなる。
LivetProperty_VB.snippet
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <Title>Livet プロパティ</Title> <Author>Livet Project</Author> <Description>プロパティを作成します</Description> <HelpUrl></HelpUrl> <SnippetTypes /> <Keywords /> <Shortcut>lprop</Shortcut> </Header> <Snippet> <References /> <Imports> <Import> <Namespace>Livet</Namespace> </Import> </Imports> <Declarations> <Literal Editable="true"> <ID>name</ID> <Type /> <ToolTip>プロパティ名</ToolTip> <Default>MyProperty</Default> <Function /> </Literal> <Literal Editable="true"> <ID>type</ID> <Type /> <ToolTip>プロパティの型</ToolTip> <Default>String</Default> <Function /> </Literal> <Literal Editable="true"> <ID>summary</ID> <Type /> <ToolTip>プロパティの説明</ToolTip> <Default>MySummary</Default> <Function /> </Literal> </Declarations> <Code Language="VB" Kind="" Delimiter="$"> <![CDATA[#Region "$name$変更通知プロパティ" Private _$name$ As $type$ ''' <summary> ''' $summary$を取得・設定します。 ''' </summary> Public Property $name$() As $type$ <DebuggerNonUserCode()> Get Return _$name$ End Get Set(ByVal value As $type$) If (Object.Equals(_$name$, value)) Then Return _$name$ = value RaisePropertyChanged("$name$") End Set End Property #End Region ]]></Code> </Snippet> </CodeSnippet> </CodeSnippets>
ViewModelCommand のスニペット改造
あと ViewModelCommand ですが、これの CenExecute 用ファンクション。スニペットでは戻り値がないためビルドエラーになります。そこで前のエントリと同じく Return True を追加しておきます。ファイルは「LivetViewModelCommand_VB.snippet」です。これをエディタで開き、編集したのち保存します。
LivetViewModelCommand_VB.snippet
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <Title>Livet ViewModelCommand</Title> <Author>Livet Project</Author> <Description>ViewModelCommandを作成します</Description> <HelpUrl></HelpUrl> <SnippetTypes /> <Keywords /> <Shortcut>lvcom</Shortcut> </Header> <Snippet> <References /> <Imports> <Import> <Namespace>Livet.Commands</Namespace> </Import> </Imports> <Declarations> <Literal Editable="true"> <ID>name</ID> <Type /> <ToolTip>コマンド名</ToolTip> <Default>MyCommand</Default> <Function /> </Literal> </Declarations> <Code Language="VB" Kind="" Delimiter="$"><![CDATA[#Region "$name$Command" Private _$name$Command As ViewModelCommand Public ReadOnly Property $name$Command() As ViewModelCommand Get If _$name$Command Is Nothing Then _$name$Command = New ViewModelCommand(AddressOf $name$, AddressOf Can$name$) End If Return _$name$Command End Get End Property Private Function Can$name$() As Boolean Return True End Function Private Sub $name$() End Sub #End Region ]]></Code> </Snippet> </CodeSnippet> </CodeSnippets>
他にも LivetListenerCommand_VB.snippet 等のスニペットが提供されてますが、自分の使いやすいように改造しとくといいと思います。
#2014/05/19 追加 : ViewModel のImports に System.Collections.ObjectModel を追加。
#2014/05/22 追記 : テンプレートキャッシュフォルダ内のファイルはVisualStudioのインストーラーで「修復」を実行すると初期化されてしまうので、テンプレートフォルダ内のファイルも同じ内容で修正しておくことをお勧めします。