代码改变世界

Caliburn笔记-Presenter的管理(wpf框架)

2009-12-28 14:08  Clingingboy  阅读(1045)  评论(0编辑  收藏  举报


回头来看caliburn是如何初始化程序界面

CaliburnApplication

CaliburnApplication继承自WPF的Application类,其初始化了caliburn的接口,同时提供了一个窗口管理的接口IWindowManager,与prism框架不同这个shell是非强制性

一.初始化

 

///<summary>
/// Raises the <see cref="E:System.Windows.Application.Startup"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.StartupEventArgs"/> that contains the event data.</param>
protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    var rootModel = CreateRootModel();
    if (rootModel == null) return;

    ShowMainWindow(rootModel);
}

/// <summary>
/// Creates the root application model.
/// </summary>
/// <returns></returns>
protected virtual object CreateRootModel()
{
    return null;
}

/// <summary>
/// Shows the main window based on the provided model.
/// </summary>
/// <param name="rootModel">The root model.</param>
protected virtual void ShowMainWindow(object rootModel)
{
    Container.GetInstance<IWindowManager>()
        .Show(rootModel, null, ExecuteShutdownModel);
}

/// <summary>
/// Executes the shutdown model.
/// </summary>
/// <param name="subordinate">The subordinate.</param>
/// <param name="completed">The completed.</param>
protected virtual void ExecuteShutdownModel(ISubordinate subordinate, Action completed)
{
    completed();


根据以上代码可得知,继承的类需要重写CreateRootModel和ExecuteShutdownModel方法.具体由IWindowManager负责处理

万事具备后IWindowManager负责初始化

初始化时容器可为Window也可以为UserControl,若是UserControl则会自动创建一个Window作为容器,但不建议这么做

/// <summary>
/// Ensures the that the view is a window or provides one.
/// </summary>
/// <param name="model">The model.</param>
/// <param name="view">The view.</param>
/// <returns></returns>
protected virtual Window EnsureWindow(object model, object view)
{
    var window = view as Window;

    if(window == null)
    {
        window = new Window
        {
            Content = view,
            SizeToContent = SizeToContent.WidthAndHeight
        };

        if(Application.Current != null
           && Application.Current.MainWindow != null)
        {
            window.Owner = Application.Current.MainWindow;
        }

        var presenter = model as IPresenter;
        if(presenter != null)
            window.Title = presenter.DisplayName;
    }
    else if (Application.Current != null
           && Application.Current.MainWindow != null)
    {
        if(Application.Current.MainWindow != window)
            window.Owner = Application.Current.MainWindow;
    }

    return window;
}


初始化Presenter

/// <summary>
/// Shows a window for the specified model.
/// </summary>
/// <param name="rootModel">The root model.</param>
/// <param name="context">The context.</param>
/// <param name="handleShutdownModel">The handle shutdown model.</param>
public void Show(object rootModel, object context, Action<ISubordinate, Action> handleShutdownModel)
{
    var window = CreateWindow(rootModel, context, handleShutdownModel);
    window.Show();
}

/// <summary>
/// Creates the window.
/// </summary>
/// <param name="rootModel">The root model.</param>
/// <param name="context">The context.</param>
/// <param name="handleShutdownModel">The handle shutdown model.</param>
/// <returns></returns>
protected Window CreateWindow(object rootModel, object context, Action<ISubordinate, Action> handleShutdownModel)
{
    var view = EnsureWindow(rootModel, _viewStrategy.GetView(rootModel, null, context));

    _binder.Bind(rootModel, view, context);

    var presenter = rootModel as IPresenter;
    if (presenter != null)
    {
        presenter.Initialize();
        presenter.Activate();

        view.Closing += (s, e) => OnShutdownAttempted(presenter, view, handleShutdownModel, e);

        view.Closed += delegate{
            presenter.Deactivate();
            presenter.Shutdown();
        };
    }

    return view;
}


以上presenter的生命周期就比较明朗了.

IPresenterManager

 

IPresenterManager is an IPresenterHost that tracks a CurrentPresenter. Whenever the CurrentPresenter is changed, the old one is deactivated/shutdown and the new one is initialized/activated.


IPresenterManager可以将一个Presenter与另外一个Presenter关联起来,两者属于父子关系,即IPresenterNode的Parent属性(IPresenterHost),一下为重写的方法

#region override method

/// <summary>
/// Determines whether this instance can shutdown.
/// </summary>
/// <returns>
///     <c>true</c> if this instance can shutdown; otherwise, <c>false</c>.
/// </returns>
public override bool CanShutdown()
{
    if(_currentPresenter != null)
        return _currentPresenter.CanShutdown();

    return true;
}

/// <summary>
/// Initializes this instance.
/// </summary>
public override void Initialize()
{
    if(!IsInitialized)
    {
        OnInitialize();

        if(_currentPresenter != null)
            _currentPresenter.Initialize();

        IsInitialized = true;
    }
}

/// <summary>
/// Shuts down this instance.
/// </summary>
public override void Shutdown()
{
    if(_currentPresenter != null)
        _currentPresenter.Shutdown();

    OnShutdown();
}

/// <summary>
/// Activates this instance.
/// </summary>
public override void Activate()
{
    if(!IsActive)
    {
        OnActivate();

        if(_currentPresenter != null)
            _currentPresenter.Activate();

        IsActive = true;
    }
}

/// <summary>
/// Deactivates this instance.
/// </summary>
public override void Deactivate()
{
    if(IsActive)
    {
        OnDeactivate();

        if(_currentPresenter != null)
            _currentPresenter.Deactivate();

        IsActive = false;
    }
}

 

在设置新的Presenter时,首先会释放之前的Presenter

/// <summary>
/// Shuts down the current presenter.
/// </summary>
/// <param name="completed">Called when the shutdown action is finished.</param>
public virtual void ShutdownCurrent(Action<bool> completed)
{
    if(_currentPresenter == null)
    {
        completed(true);
        return;
    }

    CanShutdownPresenter(
        _currentPresenter,
        isSuccess =>{
            if(!isSuccess)
            {
                completed(false);
                return;
            }

            _currentPresenter.Deactivate();
            _currentPresenter.Shutdown();

            var node = _currentPresenter as IPresenterNode;
            if (node != null) node.Parent = null;

            _currentPresenter = null;

            if(!_changingThroughProperty)
                NotifyOfPropertyChange("CurrentPresenter");

            completed(true);
        });
}


PresenterManager的Open方法会初始化关联的Presenter,并设置CurrentPresenter

/// <summary>
       /// Opens the specified presenter.
       /// </summary>
       /// <param name="presenter">The presenter.</param>
       /// <param name="completed">Called when the open action is finished.</param>
       public virtual void Open(IPresenter presenter, Action<bool> completed)
       {
           if(presenter == null)
           {
               completed(false);
               return;
           }

           Action successfulCompletion =
               () =>{
                   var node = presenter as IPresenterNode;
                   if (node != null) node.Parent = this;

                   presenter.Initialize();
                   presenter.Activate();

                   _currentPresenter = presenter;

                   if(!_changingThroughProperty)
                       NotifyOfPropertyChange("CurrentPresenter");

                   completed(true);
               };

           if(_currentPresenter != null)
           {
               CanShutdownPresenter(
                   _currentPresenter,
                   isSuccess =>{
                       if(!isSuccess)
                       {
                           completed(false);
                           return;
                       }

                       _currentPresenter.Deactivate();
                       _currentPresenter.Shutdown();

                       var node = _currentPresenter as IPresenterNode;
                       if (node != null) node.Parent = null;

                       successfulCompletion();
                   });
           }
           else successfulCompletion();
       }

 

多重Presenter管理

以上应用情景支持presenter的一开一关操作,也可以使用MultiPresenterManager和MultiPresenter这两个类进行管理,这样当设置CurrentPresenter时,则不会关闭之前的Presenter