レガシーコードからの脱却

レガシーな職場でも独学でどうにか頑張っていくブログです。

Prism自習 2 (了)

MVVMの基本クラス

Prismで提供されるMVVMの基本クラスに関してです。

BindableBase

INotifyPropertyChangedの実装クラスで、プロパティのsetメソッドでSetProperty(ref フィールドネーム, value)とすることで、PropertyChangeイベントを発行してくれます。

DelegateCommand

Commandの実装クラスはDelegateCommandです。コンストラクタの第1引数にExecute時に実行される処理を、第2に引数にCanExecute時の処理を渡して使用します。

ObservePropertyメソッドを使うことで、プロパティの変更を監視し、変更時にCanExecuteChangedを発生させることができるようです。すごい...

InteractionRequest

PrismではInteractionRequestクラスを用いてダイアログを実装するようです。 OKボタンなど普通のダイアログを出すNotificationクラス、Yes/No付きのダイアログを出すConfirmationクラスがあり、Notificationを拡張することで、独自のダイアログを実装することも可能なようです。 (Confirmationも実際には、Notificationの拡張クラスのようです。)

型引数にNotificationを指定したInteractionRequestクラスのプロパティを定義して、CommandにRaiseイベントを実装したメソッドを指定することで使用できます。

//InteractionRequestクラスのプロパティ
public InteractionRequest<Notification> NotificationRequest { get; } = new InteractionRequest<Notification>();


public DelegateCommand NotificationCommand { get; }
//コンストラクタでDelegateCommand にNotificationCommandExecuteメソッドを指定
public InteractionRequestViewModel()
        {
            this.NotificationCommand = new DelegateCommand(this.NotificationCommandExecute);
        }

//Raiseイベントの実装
private void NotificationCommandExecute()
        {
            this.NotificationRequest.Raise(new Notification { Title = "Alert", Content = "Notification message." });
        }
       <prism:InteractionRequestTrigger SourceObject="{Binding NotificationRequest, Mode=OneWay}">
            <prism:PopupWindowAction IsModal="True"
                                     CenterOverAssociatedObject="True">
                <prism:PopupWindowAction.WindowStyle>
                    <Style TargetType="Window">
                        <Setter Property="ResizeMode" Value="NoResize" />
                        <Setter Property="SizeToContent" Value="WidthAndHeight" />
                    </Style>
                </prism:PopupWindowAction.WindowStyle>
            </prism:PopupWindowAction>
        </prism:InteractionRequestTrigger>

ナビゲーション

ビュー切り替え時のナビゲーションには、PrismではPrism.Regions.INavigationAwareを用います。

//
    // 概要:
    //     Provides a way for objects involved in navigation to be notified of navigation
    //     activities.
    public interface INavigationAware
    {
        //
        // 概要:
        //     Called to determine if this instance can handle the navigation request.
        //
        // パラメーター:
        //   navigationContext:
        //     The navigation context.
        //
        // 戻り値:
        //     true if this instance accepts the navigation request; otherwise, false.
        bool IsNavigationTarget(NavigationContext navigationContext);
        //
        // 概要:
        //     Called when the implementer is being navigated away from.
        //
        // パラメーター:
        //   navigationContext:
        //     The navigation context.
        void OnNavigatedFrom(NavigationContext navigationContext);
        //
        // 概要:
        //     Called when the implementer has been navigated to.
        //
        // パラメーター:
        //   navigationContext:
        //     The navigation context.
        void OnNavigatedTo(NavigationContext navigationContext);
    }

OnNavigatedFromメソッドでは画面から離れる際の処理を、OnNavigatedToでは遷移されたときに行われる処理をそれぞれ実装します。 IsNavigationTargetメソッドでは、インスタンスがナビゲーションの要求で処理可能か返します。trueを返すときインスタンスは再利用され、falseの売位は新たなインスタンスが生成されるようです。

ナビゲーションする側はRegionManagerのRecordNavigationメソッドで管理します。NavigatetionParametersクラスを用いればパラメータを渡すことも可能です。 例では、ここでIDを渡すことで、Viewの使いまわしを管理していました。

一通り、Prism自習のコンテンツは消化しましたが、まだ完全理解には程遠いのが現状です。 あとは使いながら覚えていくしかないのですが、なに作ろうかと考えています。 また、ASP.Net MVCで作りたいものが出てきたので、そちらに少し関心が移っています。(ピンチ!) まだ、ある程度は触り続けていないと、知識が0に戻る時期にいるので、0はまずいです。

本当はASP.Net MVCでサービス作って、WPFやXamarinを使ってそれをアプリケーションからも触れるようにするのが最高なのですが、きつすぎ無理っす。

【お勉強記録】Prism6.0の自習(Bootstrapper ViewModelLocater Model Regionまで)

Prism

連休中ということで、Prism6.0を勉強してみました。

かずきさんのPrism自習用リポジトリをもとに勉強しています。

GitHub - runceel/PrismEdu: PrismLibrary japanese text.

Bootstrapper

PrismではShellという基本となる画面があってBootStrapperというUnityBootstrapperを継承したクラスで起動を管理するようです。

using HelloWorldApp.Views;
using Microsoft.Practices.Unity;
using Prism.Unity;
using System.Windows;

namespace HelloWorldApp
{
    class Bootstrapper:UnityBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
            return this.Container.Resolve<Shell>();
        }

        protected override void InitializeShell()
        {
            ((Window)this.Shell).Show();
        }
    }
}

ViewModelLocater

ViewModelLocaterはViewとViewModelとの紐づけのための機能です。 View(Xaml)のWindowやUserControlに

xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"

と書くことで、命名のルールに基づいてViewのDataContextにViewModelが割り当てられます。(View:Views.Hoge ViewModel:ViewModels.HogeViewModel といった感じ)

ModuleとRegion

Moduleでアプリケーションの機能ごとに分割して開発することが可能。 Regionは作成されたModuleをShellの特定の領域(Region)に流し込むための機能のようです。Regionのおかげで複数のModuleを柔軟に組み合わせて作ることができるようです。

Moduleで作成する画面部品は「Window」ではなく、「UserControl」ですね。当たり前ですが、ここで少しハマりました。WindowだとShell上でRegionをしっかり定義していても、反映されませんでした。 あとは普通の画面の作成と同じようにModel、View、ViewModelと作っていきます。 それができたら、IModuleインターフェースを実装したクラスを作成します。

using Microsoft.Practices.Unity;
using ModuleApp.HelloWorldModule.Models;
using ModuleApp.HelloWorldModule.Views;
using Prism.Modularity;
using Prism.Regions;

namespace ModuleApp.HelloWorldModule
{
    public class HelloWorldModule:IModule
    {
        [Dependency]
        public IUnityContainer Container { get; set; }

        [Dependency]
        public IRegionManager RegionManager { get; set; }

        public void Initialize()
        {
            this.Container.RegisterType<MessageProvider>(new ContainerControlledLifetimeManager());
            this.Container.RegisterType<object, HelloWorldView>(nameof(HelloWorldView));

            this.RegionManager.RequestNavigate("MainRegion", nameof(HelloWorldView));
        }
    }
}

Containerにクラスを登録するのと、Shellで定義したRegionに画面部品を流し込むためRegionManager.RequestNavigateを実装しました。

本体側では、ModuleをBootstrapperで組み込み、ShellでRegionを定義します。 BootstrapperクラスのConfigureModuleCatalogメソッドをオーバーライドしてModuleを追加するそうです。

protected override void ConfigureModuleCatalog()
{
    base.ConfigureModuleCatalog();

    var catalog = (ModuleCatalog)this.ModuleCatalog;
    catalog.AddModule(typeof(HelloWorldModule.HelloWorldModule));
}

ShellでのRegionの定義方法は以下の通りです。

<ContentControl prism:RegionManager.RegionName="MainRegion" />

これから

今日はPrism自習の先のコンテンツをどんどん進めていきます。 また、DIに関してもう一度学び直して、しっかり理解した方がいいと感じたので、並行してお勉強します。