WPF優秀組件推薦之Stylet(二)


上一篇文章介紹了Stylet的一些基本功能,本篇將介紹一些深入一點的功能。

  

依賴注入

在Bootstrapper 類中注入需要的對象:

    public class Bootstrapper : Bootstrapper<MainViewModel>
    {
        protected override void ConfigureIoC(IStyletIoCBuilder builder)
        {
            builder.Bind<IViewFactory>().ToAbstractFactory();
            builder.Bind<ILogger>().To<TxtLogger>().InSingletonScope();
        }
    }

使用方法:

    public class PageBasicCharacteristicViewModel : Screen
    {
        private readonly IWindowManager _windowManager; 
private readonly IViewFactory _viewFactory;
private readonly ILogger _logger; public PageBasicCharacteristicViewModel(IWindowManager windowManager, IViewFactory viewFactory, ILogger logger) { _windowManager = windowManager;
 _viewFactory = viewFactory; _logger
= logger; } }

 以上IWindowManager 是框架自帶的接口,ILog和IViewFactory是我們自己實現的接口。IViewFactory定義如下:

    public interface IViewFactory
    {
        Page1ViewModel Page1ViewModel();
        Page2ViewModel Page2ViewModel();
    }

 由於通過ToAbstractFactory方法來進行注入,不需要對該接口進行實現,但需要滿足一定的命名規則。這個方式是Stylet框架的一個小技巧,正常情況下,還是通過一個接口和一個實現類進行注入。

 

多窗口界面

一般而言,系統在功能比較多的情況下都會規划到多個頁面中,然后通過菜單來進行導航。實現的方法是,我們會創建一個主界面(ShellView),在主界面上有菜單和一個<ContentControl/>控件,當點擊不同菜單時,ContentControl容納不同的Page即可。注意:此時PageView是一個用戶控件(UserControl),而不是窗體(Window)

XMAL:

<ContentControl s:View.Model="{Binding ActiveItem}" Margin="5"/>

 CS:

 public class ShellViewModel : Conductor<IScreen>.Collection.OneActive
    {
        private readonly IWindowManager _windowManager;
        private readonly IViewFactory _viewFactory;

        public ShellViewModel(IWindowManager windowManager, IViewFactory viewFactory)
        {
            _windowManager = windowManager;
            _viewFactory = viewFactory;
        }

        protected override void OnInitialActivate()
        {
            base.OnInitialActivate();
            this.Bind(s => SelectedMenuIndex, (o, e) => SelectedMenuIndexChanged());
        }

        public List<string> Menus { get; set; } = new List<string> { "Page1", "Page2" };
        public int SelectedMenuIndex { get; set; } = -1;

        private void SelectedMenuIndexChanged()
        {
            switch (SelectedMenuIndex)
            {
                case 0: ActivateItem(Page1View ?? (Page1View = _viewFactory.Page1ViewModel())); break;
                case 1: ActivateItem(Page2View ?? (Page2View = _viewFactory.Page2ViewModel())); break;
            }
        }             

        private Page1ViewModel Page1View;
        private Page2ViewModel Page2View;        
    }
View Code

當SelectedMenuIndex的值變化時,系統將調用SelectedMenuIndexChanged()方法,此時調用ActivateItem(Screen)方法即可切換頁面。

注意ShellViewModel 的父類為Conductor<IScreen>.Collection.OneActive

以上代碼保存了一個ViewModel的實例,根據需要,我們也可以每次打開頁面時都創建一個新的ViewModel對象。

 

頁面的生命周期

不管是從Window繼承的窗口還是從UserControl繼承的用戶控件,Stylet處理的模型是一致的,都是View+ViewModel模式,且生命周期也類似。

一個Model大概有以下幾個生命周期:

        protected override void OnInitialActivate()
        {
            base.OnInitialActivate();
        }

        protected override void OnViewLoaded()
        {
            base.OnViewLoaded();
        }

        protected override void OnActivate()
        {
            base.OnActivate();
        }

        protected override void OnDeactivate()
        {
            base.OnDeactivate();
        }

        protected override void OnClose()
        {
            base.OnClose();
        }
View Code

 其調用時機和順序大家可以自己試驗一下。

 

事件

在有多個頁面時,可能需要進行頁面間的通信,Stylet框架通過事件(Event)來實現。

事件的定義:

    public class SomeEvent: PropertyChangedBase
    {
        public SomeEventArgs Args { get; set; }
    }

    public class SomeEventArgs 
    {
        public string Msg { get; set; }
    }

 

發布事件:

    public class Page1ViewModel : Screen
    {
        private readonly IEventAggregator _events;

        public Page1ViewModel(IEventAggregator events)
        {
            _events = events;
        }   

        public string Message { get; set; }
        public void SendMessage()
        {          
            _events.Publish(new SomeEvent
            {
                Args = new SomeEventArgs
                {
                    Msg = Message
                }
            });
        }
    }

 

訂閱事件:

    public class Page2ViewModel : Screen, IHandle<SomeEvent>
    {
        private readonly IEventAggregator _events;

        public Page2ViewModel(IEventAggregator events)
        {
            _events = events;
            _events.Subscribe(this);
        }

        public string RecvMsg { get; set; }
        public void Handle(SomeEvent message)
        {           
            RecvMsg = "RecvMsg=" + message.Args.Msg;
        }
    }

ViewModel通過繼承IHandle<SomeEvent>實現事件消息的處理,注意: _events.Subscribe(this);這段代碼非常重要,必須訂閱事件,不然收不到消息。

 

以上代碼下載地址:NiceComponents · Bruce/Learn WPF - 碼雲 - 開源中國 (gitee.com)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM