上一篇文章介绍了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;
}
当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();
}
其调用时机和顺序大家可以自己试验一下。
事件
在有多个页面时,可能需要进行页面间的通信,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);这段代码非常重要,必须订阅事件,不然收不到消息。
| 本博客Android APP 下载 |
![]() |
| 支持我们就给我们点打赏 |
![]() |
| 支付宝打赏 支付宝扫一扫二维码 |
![]() |
| 微信打赏 微信扫一扫二维码 |
![]() |
如果想下次快速找到我,记得点下面的关注哦!





浙公网安备 33010602011771号