The last article introduced some basic functions of style, and this article will introduce some in-depth functions.
Dependency injection
Inject the required objects into the Bootstrapper class:
public class Bootstrapper : Bootstrapper<MainViewModel> { protected override void ConfigureIoC(IStyletIoCBuilder builder) { builder.Bind<IViewFactory>().ToAbstractFactory(); builder.Bind<ILogger>().To<TxtLogger>().InSingletonScope(); } }
usage method:
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; } }
The above IWindowManager is the interface of the framework, and ILog and IViewFactory are our own interfaces. IViewFactory is defined as follows:
public interface IViewFactory { Page1ViewModel Page1ViewModel(); Page2ViewModel Page2ViewModel(); }
Since the injection is carried out through ToAbstractFactory method, the interface does not need to be implemented, but certain naming rules need to be met. This method is a trick of the style framework. Under normal circumstances, it is injected through an interface and an implementation class.
Multi window interface
Generally speaking, when the system has many functions, it will plan to multiple pages, and then navigate through the menu. The implementation method is that we will create a main interface (ShellView), which has a menu and a < ContentControl / > control. When clicking different menus, ContentControl can accommodate different pages. Note: at this time, PageView is a user control, not a 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; }
When the value of SelectedMenuIndex changes, the system will call the SelectedMenuIndexChanged() method. At this time, call the ActivateItem (Screen) method to switch pages.
Note that the parent class of ShellViewModel is conductor < iscreen > Collection. OneActive
The above code saves an instance of ViewModel. If necessary, we can also create a new ViewModel object every time we open the page.
Page lifecycle
Whether the Window inherited from Window or the user control inherited from UserControl, the model handled by style is the same, both in View+ViewModel mode, and the life cycle is similar.
A Model has the following life cycles:
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(); }
You can test the timing and sequence of its call.
event
When there are multiple pages, it may be necessary to communicate between pages. The style framework is implemented through events.
Definition of event:
public class SomeEvent: PropertyChangedBase { public SomeEventArgs Args { get; set; } } public class SomeEventArgs { public string Msg { get; set; } }
Publish event:
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 } }); } }
Subscribe to events:
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 implements the processing of event messages by inheriting ihandle < someevent >_ events.Subscribe(this); This code is very important. You must subscribe to events, or you won't receive messages.
Download address of the above code: NiceComponents · Bruce/Learn WPF - codecloud - Open Source China (gitee.com)