ホーム > Silverlight > MVVM Light Toolkitを使ってみよう。その3 MVVM Light Toolkitの場合

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


その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 タグ: ,
    1. まだコメントはありません。
    1. No trackbacks yet.

    コメントを残す

    以下に詳細を記入するか、アイコンをクリックしてログインしてください。

    WordPress.com ロゴ

    WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

    Twitter 画像

    Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

    Facebook の写真

    Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

    Google+ フォト

    Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

    %s と連携中

    %d人のブロガーが「いいね」をつけました。