アーカイブ

Posts Tagged ‘MVVM Light Toolkit’

MVVM LightがXamarinをサポート

2014年10月9日 コメントを残す

Announcing MVVM Light V5 for Windows and Xamarinより。

何度かこのブログでも紹介したMVVMLightToolkitですが、現在開催中のXamarinのイベントXamarin EvolveでXamarinのサポートをアナウンスしたそうです。

マルチプラットフォームはそこかしこに落とし穴が開いているので、こういったミドル層が絶妙な具合にサポートしてくれるとありがたいですよね。Xamarin自体のライセンスを持っていないので評価はそのうちになりますが触ってみたい技術です。

この他にV5にはマルチプラットフォーム対応版のNavigationServiceとDialogServiceの実装が含まれるようです。

Mango Sdk BetaでMVVM Lighttoolkitを使おう

Mango Sdk Betaがでてからしばらく立ちますが、WPF/Silverlight/Windows Phoneに対応したMVVMのツールキットであるMVVM LighttoolkitもMangoに対するパッチが公開されています。

バイナリーのインストール

パッチといってもバイナリーの置き換えになるようですが、安定版の MVVM Light Toolkit V3とプレビュー版の MVVM Light Toolkit V4ともにリリースされています。それぞれ次のリンクからダウンロード出来きます。

ただ、V3とV4はアセンブリが同じ名前なので、もし同居させたいならデフォルトとは違うフォルダーにインストール擦る必要がありますが、その場合、後述のテンプレートの参照先がおかしくなってしまうので、気をつけましょう。

MVVMの通常のインストールと同じように、ダウンロード後にC:\Program Filesに解答してあげましょう。MVVM LightTool V3のインストール方法はこちら。→ MVVM Light Toolkitをインストールしてみる。

V3を利用する場合は、NuGetで次のコマンドを実行すれば、インストールの作業をしなくても利用できます。

Install-Package MvvmLight

 

プロジェクトテンプレートのインストール

プロジェクトテンプレートには、通常のVisual Studio用のテンプレートと、Windows Phone用のVisual Studio Express用の2つがあります。

Visual Studio用は、Visual Studioのオプション→Tools→Options→Project and Solutionsにある、User Project Locationで確認できます。

image

デフォルトでは、ここが指定されています。

%UserProfile%\Documents\Visual Studio 2010\Projects

テンプレートをインストールすると、MvvmLight (WP7.1) がテンプレートに追加されます。

image

カテゴリー:Silverlight タグ: ,

MVVMとはを学ぶ上でこれ以上無い資料が公開中

2010年11月28日 コメントを残す

この前の勉強会でメッセージ通信の話をしていた @ugaya40 さんが、MVVMパターンと他のUIパターンというタイトルで資料を公開されています。なんというか、この前の勉強会の前半で僕が言いたかったことが凄まじく良くまとまっています。

MVVMってなに?MVCやMVPと何が違うの?何が嬉しいのって部分で悩んでいる方。必読です!!

MVVMパターンとイベント駆動開発、そしてMVC/MVP/PMパターンとの関係 – 何故MVVMなのか
http://ugaya40.net/wpf/mvvm-mvc-mvp-pm-eventdriven.html

カテゴリー:Silverlight タグ: ,

MVVMでのServiceLocatorの導入

2010年10月29日 コメントを残す

MVVM Lighttoolkit では、ViewModelはServiceLocatorが提供する仕組みになっています。いや、別にこれまでのエントリーのように、ServiceLocatorを使わなくても構築できるんですけれど、そうなっているからには何かしらの理由が有るはずです。。今回は、ServiceLocatorって何者よっていうのを解説してみようと思います。

ServiceLocatorとは

ServiceLocatorとは、プログラマーの代わりにクラスのインスタンスを管理してくれる子です。

通常クラスの実体が欲しければ、newキーワードでインスタンス化するわけですが、ServiceLocatorにクラスのインスタンスを管理してもらうことで、クラスの生成時に処理を割りこませたり、インスタンスを差し替えたりできるので、MVVMなどのレイヤー型のアーキテクチャーを採用しているプロジェクトとはそれなりに相性が良いです。これがもう少し進むとIoCが出てくるんですが、まぁそこまで行かなくてもいいでしょう。

インスタンスの差し替えと生成の割り込み

MVVMに限らないのですが、内部に持っているサービスクラスを差し替えたいことがあります。

例えば、作ったモジュールの単体テストをしたいんだけれど、依存している部分のせいでテストが行えなかったり、外部のWebサービスを参照していたり、参照するクラスライブラリがまだ実装していたりしない場合などです。このような場合、サービスの振る舞いをインターフェイスに抽象化して、サービスをテスト用のものに差し替えると、このような問題を回避できます。

具体的にはこんな感じです。

    public class SampleViewModel: ViewModelBase
    {
        public IHelloService service { get; set; }

        public SampleViewModel()
        {
        }

        public string GetHelloMessage()
        {
            return service.GetMessage();
        }
    }

    public class SampleServiceLocator
    {
        public SampleViewModel Sample
        {
            get {
                return new SampleViewModel
                {
                    service = new HelloService(),
                };
            }
        }
    }

この場合、HelloServiceはIHelloServiceとして抽象化されているので、例えばテスト時にはこんなクラスに差し替えてSampleViewModelのテストをすることができます。また、XAMLでクラスのインスタンスを作成する場合、引数なしコンストラクターが呼び出されるのですが、ServiceLocator側でプロパティーとして公開し、内部で引数付きのコンストラクターを呼び出すことも可能です。

単体テストが嬉しい

SampleViewModelの単体テストをしたいけれど、HelloServiceがまだ出来ていないとか、Webサービスを参照しているとか行った場合、HelloServiceの都合で、SampleViewModelがテストできないなんてことになります。ただ、サービスをインターフェイスに切りだしてあれば、単体テスト時にモック用のサービスに差し替えることでこんなふうにテストできますよね。

    [TestClass]
    public class Tests
    {
        [TestMethod]
        public void TestMethod1()
        {
            var target = new SampleViewModel();
            target.service = new HelloServiceMock();
            var actual = target.GetHelloMessage();
            Assert.AreEqual<string>("てすと", actual);
        }
    }
デザイン時に嬉しい

Silverlightでは、Blendなどで画面を編集する場合はコンストラクターでWebServiceからデータの取得などを行っているとデザイン画面が開けない。なんてことが起きるので、通常はViewModel内部で実行時の動作なのか、デザイン時の動作などかを判断し、コードを振り分けるなんてことをします。

この場合も、デザイン用のサービスをViewModelに与えることで、ViewModel内に実行時かどうかの判断を各必要がなくなります。たとえば、さっきのGetHelloMessageメソッド内部で判断しようとするとこうなるけれど、

        public string GetHelloMessage()
        {
            if (DesignerProperties.IsInDesignTool)
            {
                return "でざいんようめっせーじ";
            }
            else
            {
                service.GetMessage();
            }
        }

これよりは、デザイン用のサービスを用意して、生成時に差し替えて、GetHelloMessageメソッド自体では単に与えられたサービスを呼び出すほうが、ifの分岐がなくなる分嬉しいですよね。

    public class SampleServiceLocator
    {
        public SampleViewModel Sample
        {
            get {
                return new SampleViewModel
                {
                    service = (DesignerProperties.IsInDesignTool) 
                                    ? new DesingHelloService()
                                    : new HelloService(),
                };
            }
        }
    }
まとめ

MVVM Lighttoolkitでは、プロジェクトテンプレートで、MVVMのプロジェクトを作ると、ServiceLocatorをApp.xamlでインスタンス化し、各XAMLページでは、このLocatorが持っている各ViewModelをバインドすることでViewModelをViewに関連付けています。

ということで、ServiceLocatorを導入することで、クラスの生成に割り込めるので、テストがしやすくなったり、ブレンドでのデザインがしやすくなるというのを確認してもらえたのではないかと思います。

カテゴリー:Silverlight タグ: ,

MVVM Light Toolkitを使ってみよう。その3 MVVM Light Toolkitの場合

2010年10月11日 コメントを残す

その2 MVVMの復習では、MVVMパターンでどのようにアプリケーションを作成するかの復習をしました。今回は前回のアプリケーションと同じものをMVVM Light Toolkitを使って作成してみます。MVVM Light Toolkitには その1 MVVM Light Toolkitをインストールしてみる。で環境設定をしたとおり、プロジェクトテンプレートやアイテムテンプレートが含まれますが、とりあえずこのテンプレートは使わずに、通常のSilverlightアプリケーションとして作成されたアプリケーションからMVVM Light Toolkitを使ってみようと思います。

アセンブリの参照

MVVM Light Toolkitで利用するアセンブリを参照します。このアセンブリの中には、前回自前で作成したRelayCommandやViewModelのベースクラスなどが含まれます。

その1で説明した通りにインストールしている場合、必要なアセンブリは次のフォルダーにあります。

C:\Program Files\Laurent Bugnion (GalaSoft)\Mvvm Light Toolkit\Binaries\Silverlight4

image

コードの変更

今回行ったコードの変更は次の2つです。

  • 継承元をINotifyPropertyChanged⇒GalaSoft.MvvmLight.ViewModelBaseへ変更
  • RelayCommandをMVVM Light Toolkit標準のものへ変更
  • using System.Windows;
    using GalaSoft.MvvmLight;
    using GalaSoft.MvvmLight.Command;
    using PlaneMVVMApplication.Web.Model;
    using PlaneMVVMApplication.Services;
    
    namespace PlaneMVVMApplication.Views.Hello
    {
        public class UserViewModel: ViewModelBase
        {
            public IHelloService service { get; set; }
    
            public UserViewModel()
            {
                service = new HelloService();
                OnSave = new RelayCommand<ユーザー>(Save, parameter => true);
                OnLoad = new RelayCommand(Load, () => true);
            }
    
            private ユーザー _ユーザー;
            public ユーザー ユーザー
            {
                get { return _ユーザー; }
                set
                {
                    if (ユーザー == value)
                        return;
                    _ユーザー = value;
                    RaisePropertyChanged("ユーザー");
                }
            }
    
            public RelayCommand<ユーザー> OnSave { get; private set; }
            public void Save(ユーザー parameter)
            {
                // Save
                MessageBox.Show(string.Format(
                        "Id={0}\n名前={1}\n郵便番号={2}",
                        ユーザー.Id, ユーザー.名前, ユーザー.郵便番号));
            }
    
            public RelayCommand OnLoad { get; private set; }
            public void Load()
            {
                // 実際にはサービス経由でユーザーを検索する。
                ユーザー = new ユーザー
                {
                    Id = 1,
                    名前 = "かるあ",
                    郵便番号 = "",
                };
            }
        }
    }
    

実行すると、前回と同じ結果になるのを確認できると思います。

    画面読込時に、データを検索したい

    これまでのサンプルでは、画面ロード時にユーザーのインスタンスが空の場合は、新ししく作成していましたが、実際にはサーバーから対象のユーザーを検索してデータを表示したいといった要望があるでしょう。

    このような場合、この詳細画面を呼び出す側のページでユーザーIdなどを詳細画面に伝え、Loadedイベント等でサーバー側にユーザーの情報を問い合せます。単純に考えれば、UserViewModelのLoadメソッドをLayoutRootのLoadedイベントで呼び出せばいいのですが、単純にViewModelのメソッドをViewのイベントから呼び出すことはできません。

    ここで登場するのが、MVVM Light ToolkitのEventToCommandビヘイビアです。このビヘイビアは名前の通りEventのイベントハンドラーに対してDataContextにバインドされたViewModelのComandをバインドすることができます。

    EventToCommandビヘイビアの追加

    ビヘイビアの適用はVisual Studioを使って、直にXAMLを記述することも可能ですが、ここではExpressionBlendを使ってビヘイビアを適用してみましょう。UserView.xamlをExpressionBlendで開き、アセットライブラリーからEventToCommandビヘイビアをLoyoutRootにドロップします。

    image

    コマンドを起動するイベントの設定

    EventNameにLoadedイベントを設定します。

    無題

    コマンドをバインド

    Commandのバインドを行ないます。■部分をクリックして、データバインドを選択、UserViewModelのOnLoadメソッドを設定します。

    image

ここまで設定すると次のようにビヘイビアが設定され、起動時にOnLoadedイベントから、ViewModelのOnLoadメソッドが実行されるようになります。

<navigation:Page 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
    xmlns:local="clr-namespace:PlaneMVVMApplication.Views.Hello"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
    xmlns:GalaSoft_MvvmLight_Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL4" 
    x:Class="PlaneMVVMApplication.Views.Hello.HelloView"
    mc:Ignorable="d"
    Title="HelloView Page">

    <navigation:Page.Resources>
        <local:UserViewModel x:Key="viewModel" />
</navigation:Page.Resources>
    
    <Grid x:Name="LayoutRoot" DataContext="{StaticResource viewModel}" Height="120" Width="250">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="60"/>
            <ColumnDefinition Width="70*"/>
        </Grid.ColumnDefinitions>
        
    	<i:Interaction.Triggers>
    		<i:EventTrigger>
    			<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding OnLoad, Mode=OneWay}"/>
    		</i:EventTrigger>
    	</i:Interaction.Triggers>
        
        <TextBlock Text="Id" Grid.Column="0" Grid.Row="0" />
        <TextBlock Text="{Binding ユーザー.Id}" Grid.Column="1" Grid.Row="0" />
        
        <TextBlock Text="名前" Grid.Column="0" Grid.Row="1" />
        <TextBox Text="{Binding ユーザー.名前, Mode=TwoWay}" Grid.Column="1" Grid.Row="1"/>

        <TextBlock Text="郵便番号" Grid.Column="0" Grid.Row="2" />
        <TextBox Text="{Binding ユーザー.郵便番号, Mode=TwoWay}" Grid.Column="2" Grid.Row="2"/>

        <StackPanel Orientation="Horizontal" Grid.Column="1" Grid.Row="3">
            <Button Content="読み込み" Command="{Binding OnLoad}" />
            <Button Content="保存" Command="{Binding OnSave}" CommandParameter="{Binding ユーザー}" />
        </StackPanel>
    </Grid>
</navigation:Page>
    実際にサーバーのサービスを呼び出す

    ここまでで、ViewModelのデータを読み込んだり、書き込んだり、メソッドを呼び出したりといったViewModelの大まかな流れをMVVM Light Toolkit を使って実装してみました。それでは実際に、Loadメソッドが呼ばれたタイミングでWCFを通じてWebサービス経由でデータの読込を行って見ましょう。

    サービス側はまぁ単純にこんなサービスを提供してみることとします。

        [ServiceContract(Namespace = "")]
        [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        public class Service1
        {
            [OperationContract]
            public ユーザー FindユーザーById(int Id)
            {
                return new ユーザー
                {
                    Id = 1,
                    名前 = "かるあ",
                    郵便番号 = "",
                };
            }
        }

     

    Silverlight側では、上記のWCFサービスをラップするHelloServiceクラス経由でサービスを呼び出します。HelloServiceクラス内部では、WCFのプロキシクラスをインスタンスとして持ちます。FindユーザーByIdメソッドでは、WCFで公開されたメソッドを呼び出し、渡されたコールバック変数を呼び出し終了時のイベントに設定しています。

    using System;
    using PlaneMVVMApplication.ServiceReference1;
    
    namespace PlaneMVVMApplication.Services
    {
        public class HelloService
        {
            private Service1Client service = new ServiceReference1.Service1Client();
    
            public void FindユーザーById(int Id, Action<object, FindユーザーByIdCompletedEventArgs> callback)
            {
                service.FindユーザーByIdCompleted += new EventHandler<FindユーザーByIdCompletedEventArgs>(callback);
                service.FindユーザーByIdAsync(Id);
            }
        }
    }

    ViewModel側では、ViewModelのコンストラクターでHelloServiceをインスタンス化し

    public IHelloService service { get; set; }
    
    public UserViewModel()
    {
        service = new HelloService();
        OnSave = new RelayCommand<ユーザー>(Save, parameter => true);
        OnLoad = new RelayCommand(Load, () => true);
    }

    Loadメソッド実行時にサービスを呼び出します。

    public RelayCommand OnLoad { get; private set; }
    public void Load()
    {
        service.FindユーザーById(1, (s, e) => {
            ユーザー = new ユーザー
            {
                Id = e.Result.Id,
                名前 = e.Result.名前,
                郵便番号 = e.Result.郵便番号,
            };
        });
    }
    次回予告

    なんとなくそれっぽいものはできましたね。次回は、Service Locatorを使ったViewModelの生成とBlendとさらに仲良くなる方法にあたりを見てみましょうか。

    カテゴリー:Silverlight タグ: ,

    MVVM Light Toolkitを使ってみよう。その2 MVVMの復習

    2010年10月3日 1件のコメント

    さて、ぼーっとしているうちに日があいてしまいましたが、MVVM Light Toolkitの使い方を説明する前に、MVVMについて復習しておきましょう。

    今回のサンプル

    MVVMとは?

    Model-View-ViewModelの頭文字をとった、アプリケーションのUI分離パターンの一つです。 UI分離パターンを使うと、各層の依存関係が薄くなり、アプリケーションの修正、複数人数での分散開発、単体テストのしやすさなどの面で利点があります。

    また、ExpressionBlend 4からは、デザインツール側でもMVVMがサポートされていることから、デザインツール側でアプリケーションをデザインする際にも各層が分離されているということが重要になってきます。

    MVVMでは、有名なMVC(Model-View-Controller)をベースに、バインド機能をより使いやすい形に変換したパターンになっています。 MVC、MVPの詳しい説明に関しては、猪股さんの解説が分かりやすいのでこちらへw。
    http://matarillo.com/general/uipatterns.php

    実はMVVMの考え方は、この中で解説されているアプリケーションモデルにとても似ています。MVVMでは、MVCが苦手としているModelのデータとViewのデータの同期と、Modeleがもつメソッドの呼び出しなどを、ViewからViewModelへのバインド経由で実行するといった形を取ります。

    ViewModel経由でバインドされることで、ModelとViewModelはViewから切り離され、テストや分散開発がしやすい状況になるわけです。

    何はともあれ、最初のMVVMアプリケーション

    まずはMVVMがどんなものかを理解するためにも、MVVM Light Toolkitを使わないで簡単なMVVMの更新処理を書いてみましょう。

    どんなサンプル?

    今回サンプルにするのは、ユーザーの編集画面です。このサンプルでは入力されたデータを保存したり、読出したりするサンプルです。 サンプルではViewModelにロードされたユーザー情報と、データの保存、読み込みと行ったコマンドを、Viewにバインドしユーザーのアクションに応じてViewModelからModelの情報を操作します。

    128601374947516122036_20101002-01_20101002190229

    Model-(データとデータに対する振る舞い)

    モデルは特定のドメイン(領域)の問題を解決するために分析されたデータモデルです。

    今回は単にユーザーを識別するIdや名前、郵便番号のデータを持つエンティティークラスです。特にこのモデルに対する振る舞いは定義していません。

    public class ユーザー
    {
        public int Id { get; set; }
        public string 名前 { get; set; }
        public string 郵便番号 { get; set; }
    }
    ViewModel -(ViewにバインドしてModelの操作を行う)

    Viewに対してバインドを行うモデルとモデルに対するコマンド、他のViewModelに対するメッセージなどを公開します。

    プロパティーの実装 View側では、ViewModelで公開されたプロパティーに対してバインドを行うため、ViewModelではユーザークラスをプロパティーとして公開します。 またView側での変更通知を有効にするため、INotifyPropertyChangedインターフェイスを実装します。

    public class UserViewModel: INotifyPropertyChanged
    {
       public UserViewModel()
       {
           if (ユーザー == null)
               ユーザー = new ユーザー();
       }
    
       #region プロパティー
       // Viewにバインドするため、ユーザーモデルをプロパティーとして公開する。
       private ユーザー _ユーザー;
       public ユーザー ユーザー
       {
           get { return _ユーザー; }
           set
           {
               if (ユーザー == value)
                   return;
               _ユーザー = value;
               RaisePropertyChange("ユーザー");
           }
       }
       #endregion
    
       #region INotifyPropertyChanged
       public event PropertyChangedEventHandler PropertyChanged;
       public void RaisePropertyChange(string propertyName)
       {
           if (PropertyChanged == null)
               return;
           PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
       }
       #endregion
    
       #region コマンド
       // コマンド
       #endregion
    }

    コマンドの実装プロパティー同様に、Viewからバインドするコマンド(OnSave、OnLoad)を定義し、RelayCommand経由でそれぞれの処理(Saveメソッド、Loadメソッド、)に関連付けます。 コマンド自体はICommandインターフェイスを実装しているクラスである必要がありますが、コマンドごとにクラスを定義するのも大変なので、更新処理をデリゲートとして定義できるRelayCommandクラスを作成しています。(RelayCommandについては後述)

    また、SaveメソッドとLoadメソッドはサンプルとして固定データを読み込んだり、Viewで入力されたデータを表示するようにしています。実際にはWCFやWCF RIA Servicesなどを使って、サーバー側のサービス経由でデータの操作を行ないます。

    public class UserViewModel: INotifyPropertyChanged
    {
       public UserViewModel()
       {
           if (ユーザー == null)
               ユーザー = new ユーザー();
    
           OnSave = new RelayCommand(Save, parameter =&gt; true);
           OnLoad = new RelayCommand(Load, parameter =&gt; true);
       }
    
       #region プロパティー
       #endregion
       #region INotifyPropertyChanged
       #endregion
    
       #region コマンド
       public RelayCommand OnSave { get; private set; }
       public void Save(object parameter)
       {
           // 入力されたデータを表示する。
           // 実際はサービスの呼び出しを行ってデータをサーバー側に保存する。
           MessageBox.Show(string.Format(
                   "Id={0}\n名前={1}\n郵便番号={2}",
                   ユーザー.Id, ユーザー.名前, ユーザー.郵便番号));
       }
    
       public RelayCommand OnLoad { get; private set; }
       public void Load(object parameter)
       {
           // 固定データをユーザークラスにロードする。
           // 実際にはサービス経由でユーザーを検索する。
           ユーザー = new ユーザー
           {
               Id = 1,
               名前 = "かるあ",
               郵便番号 = "181-0013",
           };
       }
       #endregion
    }
    View-(Silverlightの画面)

    ViewはViewModelを表示するためのユーザーインターフェイスです。

    ViewModelのインスタンス化

    View側でViewModelを利用するためにxmlnsでxmlの名前空間(9行目)を定義します。 同時にStaticResourceとしてlocal:UserViewModelを定義(12行目~14行目)することで、Viewが実態化したさいにViewModelも実体化されます。

    <navigation:Page
       x:Class="PlaneMVVMApplication.Views.Hello.HelloView"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       mc:Ignorable="d"
       xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
       xmlns:local="clr-namespace:PlaneMVVMApplication.Views.Hello"
       Title="HelloView Page">
    
       <UserControl.Resources>
           <local:UserViewModel x:Key="viewModel" />
       </UserControl.Resources>
       <Grid x:Name="LayoutRoot" DataContext="{StaticResource viewModel}" Height="120" Width="250">
       </Grid>
    </navigation:Page>
    プロパティーとコマンドのバインド

    GridのDataContextに、StaticResourceとして定義したUserViewModelをバインドし、TextBoxやTextBlockにユーザーの各プロパティー情報をバインドします。また、読み込みや保存と行ったボタンに対し、ViewModelで公開したOnLoadやOnSaveといったRelayCommandをバインドします。

    <Grid x:Name="LayoutRoot" DataContext="{StaticResource viewModel}" Height="120" Width="250">
           <!-- RowDefinitions, ColumnDefinitionsの定義 -->
    
           <TextBlock Text="Id" Grid.Column="0" Grid.Row="0" />
           <TextBlock Text="{Binding ユーザー.Id}" Grid.Column="1" Grid.Row="0" />
    
           <TextBlock Text="名前" Grid.Column="0" Grid.Row="1" />
           <TextBox Text="{Binding ユーザー.名前, Mode=TwoWay}" Grid.Column="1" Grid.Row="1"/>
    
           <TextBlock Text="郵便番号" Grid.Column="0" Grid.Row="2" />
           <TextBox Text="{Binding ユーザー.郵便番号, Mode=TwoWay}" Grid.Column="2" Grid.Row="2"/>
    
           <StackPanel Orientation="Horizontal" Grid.Column="1" Grid.Row="3">
               <Button Content="読み込み" Command="{Binding Path=OnLoad}" />
               <Button Content="保存" Command="{Binding Path=OnSave}" CommandParameter="{Binding ユーザー}"  />
           </StackPanel>
       </Grid>

    Silverlight 3まではButtonコントロールはICommandインターフェイスを実装していなかったので、コマンドバインディングを使いたいときはMVVM Light ToolkitやPrismが提供するコマンドバインディングを利用する必要がありました。

    サンプルの実行結果

    読み込みボタンをクリックすると、ViewModelに定義したLoadメソッドが呼び出され、ユーザーがViewに表示されます。 また、保存ボタンをクリックすると、ViewModelに定義したSaveメソッドが呼び出され、Viewで修正したデータが表示されるのを確認できます。

    128601385345416209878_20101002-02

    バインドの機能を利用してUIとViewModelのデータとコマンドをバインドすることで、Viewで入力されたデータの詰め替えとメソッドの呼び出しロジックがSilverlightのコードビハインドからなくなったことを確認できると思います。

    RelayCommand

    コマンドバインドでバインドできるコマンドは、ICommandインターフェイスを実装したクラスである必要があります。 ただ、保存や読込といったコマンドごとにクラスを作っていくのは大変なので、多くの場合RelayCommandというユーティリティークラスを各自定義してコマンドをバインドします。

    次回予告

    Silverlight 4になり、ボタンなどの一部のコントロールにコマンドバインディングがサポートされましたが、それ以外のイベントに対するコマンドのバインドはサポートされていません。また、ViewModelのベースクラスやRelayCommandなど自前で作る必要がありますし、ViewModelの定型コードを書くためのスニペットなども複数人で開発する際は書かせないでしょう。

    ここらへんを楽にしてくれるのが今回紹介するMVVM Light Toolkitというワケですね。

    ということで、次回から実際にMVVM Light Toolkitを使ってどんなふうに実装していくかを見ていきます。

    参考

    日本語

    カテゴリー:Silverlight タグ: ,

    MVVM Light Toolkitをインストールしてみる。

    2010年10月3日 3件のコメント

    こんにちは、もう夏も終わりですね。かなり久々なエントリーです。

    MVVM Light ToolkitはWPFやSilverlight、Windows Phone 7でMVVMでアプリケーションを作成するためのフレームワークです。なんとなく、こいつを使ってサンプルでも作ってみるか!!という感じなので数回ほどMVVM Light Toolkitを取り上げてみます。

    0.MVVM Light Toolkitのダウンロード

    MVVM Light Toolkitの2010/09/11時点の最新版はV3 SP1
    http://mvvmlight.codeplex.com/

    1.MVVM Light Toolkitのバイナリーを展開

    GalaSoft.MvvmLight.Binaries.V3.zip を展開して、とりあえず次のフォルダーに配置する。 (UACの制御がかかると思うので注意。)
    ⇒ C:\Program Files\Laurent Bugnion (GalaSoft)\Mvvm Light Toolkit

    2.Visual Studioのテンプレートを展開

    GalaSoft.MvvmLight.Templates.V3.VS10.zip を展開して、ユーザーテンプレートフォルダーに配置する。 ユーザーテンプレートフォルダーは、Visual Studio 2010の場合、デフォルトではここ。
    ⇒ %UserProfile%\Documents\Visual Studio 2010\Templates\

    Visual Studio 2010の場合は、ここで確認する。
    ⇒ Visual Studio のメニュー[ツール]
    ⇒[オプション]
    ⇒[プロジェクトおよびソリューション]
    ⇒[ユーザー プロジェクト テンプレートの場所]

    Visual Studio のメニュー[ツール]
    ⇒[オプション]
    ⇒[プロジェクトおよびソリューション]
    ⇒[ユーザー アイテム テンプレートの場所]

    128421519848316228921_image_2

    3.スニペットの展開

    GalaSoft.MvvmLight.Snippets.V3.zip を展開して、ユーザーのコードスニペットフォルダーに配置する。ユーザーのコードスニペットフォルダーは、Visual Studio 2010の場合、デフォルトではここ。
    ⇒ %UserProfile%\Documents\Visual Studio 2010\Code Snippets\Visual C#\My Code Snippets

    Visual Studio 2010の場合は、ここで確認する。
    ⇒ Visual Studio のメニュー[ツール]
    ⇒[コードスニペット マネージャー]
    ⇒言語をC#に変更
    ⇒My Code Snippetsを選択

    128421520464916113898_image_4

    4.Expression Blend のテンプレートの展開

    GalaSoft.MvvmLight.Templates.V3.Blend4.zip または、GalaSoft.MvvmLight.Templates.V3.Blend3.zipを展開して、Expression Blendのテンプレートフォルダーに配置する。
    ⇒ %UserProfile%\Documents\Expression\Blend4 (または、Blend3)

    128421520809716113941_image_8128421521270116228921_image_10

    5.確認

    Visual Studio や Expression Blendで新しいプロジェクトを作成しようとすると、プロジェクトテンプレートにMVVM Light Toolkitのテンプレートが追加されます。

     
    と、今日はここまで。

    カテゴリー:Silverlight タグ: ,