Livet をカスタマイズする。

#以下の記事は旧いバージョンによる記事です。最新版はこちらを参考にしてください。
国産 MVVM インフラ「Livet」も徐々に普及しつつあるようで、MSDN フォーラムでもちょくちょく名前を聞くようになってきました。
私も業務で使い倒してますが、VB プロジェクトで Livet 使う場合、少し気が利いてない箇所があるのは事実です。*1 また実務で作業してると、スニペットを自分用に改造したい欲求にかられてきます。そこで今回は Livet の改造法を公開します。

以下 VB 向けの改造ですが、応用すれば C# でもいけると思いますよ。

スニペットの改造

別に既定で入ってる必要ないのですが、プロパティの先頭にコメントが入っていると何かと便利なので、スニペットに設定したくなりました。
Livet をインストールするとスニペット

Visual Studio 2010 のインストールフォルダ/VB(C# ならC#フォルダ)/Snippets/1041/application


に展開されます。VB の場合、Livet用プロパティのスニペットは LivetProperty_VB.snippet。エディタで開いて、XMLコメントを加えます。

<?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>
      </Declarations>
      <Code Language="VB" Kind="" Delimiter="$">
        <![CDATA[
#Region "$name$変更通知プロパティ"
Private _$name$ As $type$

''' <summary>
''' を取得・設定します。
''' </summary>
Public Property $name$() As $type$
    Get
        Return _$name$
    End Get
    Set(ByVal value As $type$)
        If (_$name$ = value) Then Return
        _$name$ = value
        RaisePropertyChanged("$name$")
    End Set
End Property
#End Region
]]></Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>


このファイルの

''' <summary>
''' を取得・設定します。
''' </summary>

が、自分で追加した箇所です。保存して lprop スニペットを実行するとこうなります。


今回スニペットの中身に初めて触れる機会ができたのですが、スニペットの構造が判ってくると、標準スニペットも改造したい欲求にかられますねw


ViewModelCommand のスニペット改造

#2012/02/21 追加
あと ViewModelCommand ですが、これの CenExecute 用ファンクション。スニペットでは戻り値がないためビルドエラーになります。そこでとりあえず Return True を追加しておきましょう。ファイルは「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

    ''' <summary>
    ''' コマンドです。
    ''' </summary>
    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>

プロジェクトテンプレートの変更

お次はテンプレートの変更です。VB のテンプレートには Livet のインポートが宣言されてないんですよね。そこで追加しちゃいます。
あと、個人的に Option ステートメントの宣言をするようしてますので、これもついでに加えます。

Option Explicit On
Option Strict On

Imports Livet


まずプロジェクトテンプレートの編集。テンプレートは以下のフォルダにある Livet_WPF4_VB.zip です。

Visual Studio 2010 のインストールフォルダ/Common7/IDE/ProjectTemplatesCache/VisualBasic/Windows/1041


この ZIP フォルダに含まれる以下の三つのファイルを変更します。

  • Models/Model.vb
  • ViewModels/MainWindowViewModel.vb
  • Views/MainWindow.xaml.vb

この三つのファイルに Option ステートメントの宣言と、Livet のインポートを加えます。
あと作業していて思ったのが、ViewModel.vb には Livet.Commands と Livet.Messaging.Windows のインポートが必要だということ。そこで MainWindowViewModel.vb の内容を以下のように変えちゃいます。

Option Explicit On
Option Strict On

Imports Livet
Imports Livet.Commands
Imports Livet.Messaging.Windows

Public Class MainWindowViewModel
    Inherits ViewModel

    'コマンド、プロパティの定義にはそれぞれ 
    ' 
    '  lvcom   : ViewModelCommand
    '  lvcomn  : ViewModelCommand(CanExecute無)
    '  llcom   : ListenerCommand(パラメータ有のコマンド)
    '  llcomn  : ListenerCommand(パラメータ有のコマンド・CanExecute無)
    '  lprop   : 変更通知プロパティ
    '  
    'を使用してください。

    'ViewModelからViewを操作したい場合は、
    'Messengerプロパティからメッセージ(各種InteractionMessage)を発信してください。

    'UIDispatcherを操作する場合は、DispatcherHelperのメソッドを操作してください。
    'UIDispatcher自体はApplication.xaml.vbでインスタンスを確保してあります。

    'Modelからの変更通知などの各種イベントをそのままViewModelで購読する事はメモリリークの
    '原因となりやすく推奨できません。ViewModelHelperの各静的メソッドの利用を検討してください。

End Class


VB の ViewModel クラスファイルに Import が足りないのは、開発者のugaya40 さんも認識しておられるので、たぶん次期バージョンには対応してもらえると思います。あと、個人的に Model を Friend から Public に変更しちゃいました。Friend じゃテストしづらいですからね。


項目テンプレートの変更

でもこんだけじゃ足りなくて、整合性を保つため、項目テンプレートの変更も必要になってきました。「新しい項目の追加」で出てくるアレですね。Livet が提供する五つのアイテムは、以下のフォルダにインストールされてます。

Visual Studio 2010 のインストールフォルダ\Common7\IDE\ItemTemplatesCache\VisualBasic\WPF\1041

これらのファイルを同様に編集し保存します。これで次回から項目を追加する際、変更が反映されてます。


#なにかのお役に立てば幸いです。


 

*1:まぁ仕方ないんですがねェ