惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
NISL@THU
NISL@THU
E
Exploit-DB.com RSS Feed
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
K
Kaspersky official blog
Project Zero
Project Zero
Cisco Talos Blog
Cisco Talos Blog
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
S
Schneier on Security
G
GRAHAM CLULEY
The Hacker News
The Hacker News
T
Threat Research - Cisco Blogs
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyberwarzone
Cyberwarzone
C
CERT Recently Published Vulnerability Notes
T
Tor Project blog
AWS News Blog
AWS News Blog
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
爱范儿
爱范儿
P
Privacy International News Feed
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
S
Securelist
G
Google Developers Blog
The Last Watchdog
The Last Watchdog
Google Online Security Blog
Google Online Security Blog
美团技术团队
F
Fortinet All Blogs
小众软件
小众软件
Recorded Future
Recorded Future
V
Visual Studio Blog
B
Blog RSS Feed
H
Help Net Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
Blog — PlanetScale
Blog — PlanetScale
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
Martin Fowler
Martin Fowler
Latest news
Latest news
Spread Privacy
Spread Privacy
H
Heimdal Security Blog

博客园 - seabluescn

WPF开发快速入门【8】WPF进行简单的3D开发 WPF开发快速入门【7】WPF的拖放功能(Drag and Drop) WPF开发快速入门【6】下拉框与枚举类型 WPF开发快速入门【5】DataGrid的使用 WPF开发快速入门【4】自定义控件与用户控件 WPF开发快速入门【3】WPF的基本特性(附加属性) WPF开发快速入门【2】WPF的基本特性(Style、Trigger、Template) WPF开发快速入门【1】WPF的布局 WPF开发快速入门【0】前言与目录 WPF优秀组件推荐之FreeSpire WPF优秀组件推荐之LiveCharts WPF优秀组件推荐之MahApps WPF优秀组件推荐之Stylet(一) TensorFlow.NET机器学习入门【9】后记 TensorFlow.NET机器学习入门【8】采用GPU进行学习 TensorFlow.NET机器学习入门【7】采用卷积神经网络(CNN)处理Fashion-MNIST TensorFlow.NET机器学习入门【6】采用神经网络处理Fashion-MNIST TensorFlow.NET机器学习入门【5】采用神经网络实现手写数字识别(MNIST) TensorFlow.NET机器学习入门【4】采用神经网络处理分类问题
WPF优秀组件推荐之Stylet(二)
seabluescn · 2022-03-07 · via 博客园 - seabluescn

上一篇文章介绍了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)