Prism是一个用于WPF、Xamarin Forms、WinUI等的MVVM框架,刚刚学习,这里只是个人总结的一些知识点笔记。
IoC#
IContainerProvider
1
2
3
4
| protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
|
1
2
3
4
5
6
| public void OnInitialized(IContainerProvider containerProvider)
{
var regionManager = containerProvider.Resolve<IRegionManager>();
var viewA = containerProvider.Resolve<ViewA>();
...
}
|
IContainerRegistry
1
2
3
4
5
6
7
8
9
| // App.xaml.cs
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register<IApplicationCommands, ApplicationCommands>();
containerRegistry.RegisterDialog<NotificationDialog, NotificationDialogViewModel>();
containerRegistry.RegisterForNavigation<Page1>();
containerRegistry.RegisterForNavigation<Page2>();
...
}
|
Module#
IModule
1
2
3
4
5
6
7
8
9
10
| public class SimpleModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
|
使用App.config加载模块
1
2
3
4
5
6
7
8
9
10
11
12
| <!-- App.config -->
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="modules" type="Prism.Modularity.ModulesConfigurationSection, Prism.Wpf" />
</configSections>
<startup>
</startup>
<modules>
<module assemblyFile="Simple.dll" moduleType="Simple.SimpleModule, Simple, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="SimpleModule" startupLoaded="True" />
</modules>
</configuration>
|
1
2
3
4
5
6
7
8
9
10
11
12
| // App.xaml.cs
public partial class App : PrismApplication
{
...
protected override IModuleCatalog CreateModuleCatalog()
{
return new ConfigurationModuleCatalog();
}
...
}
|
直接引用加载模块
1
2
3
4
5
6
7
8
9
10
11
12
| // App.xaml.cs
public partial class App : PrismApplication
{
...
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
moduleCatalog.AddModule<SimpleModule>();
}
...
}
|
指定模块文件夹
1
2
3
4
5
6
7
8
9
10
11
12
| // App.xaml.cs
public partial class App : PrismApplication
{
...
protected override IModuleCatalog CreateModuleCatalog()
{
return new DirectoryModuleCatalog() { ModulePath = @".\Modules" };
}
...
}
|
使用ModuleCatalog
加载模块
1
2
3
4
5
6
7
8
| <m:ModuleCatalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:m="clr-namespace:Prism.Modularity;assembly=Prism.Wpf">
<m:ModuleInfo ModuleName="Simple"
ModuleType="Simple.SimpleModule, Simple, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</m:ModuleCatalog>
|
1
2
3
4
5
6
7
8
9
10
11
12
| // App.xaml.cs
public partial class App : PrismApplication
{
...
protected override IModuleCatalog CreateModuleCatalog()
{
return ModuleCatalog.CreateFromXaml(new Uri("/Modules;component/ModuleCatalog.xaml", UriKind.Relative));
}
...
}
|
Command#
DelegateCommand
1
2
3
4
5
6
7
8
9
10
11
12
| public DelegateCommand ExecuteDelegateCommand { get; }
public DelegateCommand<string> ExecuteGenericDelegateCommand { get; }
public DelegateCommand DelegateCommandObservesProperty { get; }
public DelegateCommand DelegateCommandObservesCanExecute { get; }
ExecuteDelegateCommand = new DelegateCommand(Execute, CanExecute);
DelegateCommandObservesProperty = new DelegateCommand(Execute, CanExecute).ObservesProperty(() => IsEnabled);
DelegateCommandObservesCanExecute = new DelegateCommand(Execute).ObservesCanExecute(() => IsEnabled);
ExecuteGenericDelegateCommand = new DelegateCommand<string>(ExecuteGeneric).ObservesCanExecute(() => IsEnabled);
|
CompositeCommand
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| public CompositeCommand SampleCommand { get; } = new CompositeCommand(true);
...
DelegateCommand UpdateCommand = new DelegateCommand(Update).ObservesCanExecute(() => CanUpdate);
SampleCommand.RegisterCommand(UpdateCommand);
...
private void OnIsActiveChanged()
{
UpdateCommand.IsActive = IsActive;
IsActiveChanged?.Invoke(this, new EventArgs());
}
|
Event To Command
1
2
3
4
5
6
| <i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<prism:InvokeCommandAction Command="{Binding PersonSelectedCommand}"
CommandParameter="{Binding ElementName=ListOfPerson, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
|
BindableBase#
1
2
3
4
| public class ViewAViewModel : BindableBase, IActiveAware
{
...
}
|
ViewModelLocator#
AutoWireViewModel
1
2
3
4
| <Window x:Class="Demo.Views.MainWindow"
...
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
|
更改命名约定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| // App.xaml.cs
public partial class App : PrismApplication
{
...
protected override void ConfigureViewModelLocator()
{
base.ConfigureViewModelLocator();
ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
{
var viewName = viewType.FullName.Replace(".ViewModels.", ".CustomNamespace.");
var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
var viewModelName = $"{viewName}ViewModel, {viewAssemblyName}";
return Type.GetType(viewModelName);
});
}
...
}
|
自定义ViewModel注册
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| // App.xaml.cs
public partial class App : PrismApplication
{
...
protected override void ConfigureViewModelLocator()
{
base.ConfigureViewModelLocator();
// type / type
ViewModelLocationProvider.Register(typeof(MainWindow).ToString(), typeof(CustomViewModel));
// type / factory
ViewModelLocationProvider.Register(typeof(MainWindow).ToString(), () => Container.Resolve<CustomViewModel>());
// generic factory
ViewModelLocationProvider.Register<MainWindow>(() => Container.Resolve<CustomViewModel>());
// generic type
ViewModelLocationProvider.Register<MainWindow, CustomViewModel>();
}
...
}
|
EventAggregator#
IEventAggragator
1
2
3
4
| public interface IEventAggregator
{
TEventType GetEvent<TEventType>() where TEventType : EventBase;
}
|
创建消息事件类
1
2
3
| public class SimpleMessageEvent : PubSubEvent<string>
{
}
|
订阅事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| private readonly IEventAggregator eventAggregator;
public MainPageViewModel(IEventAggregator ea)
{
eventAggregator = ea;
ea.GetEvent<SimpleMessageEvent>().Subscribe(ShowMessage);
// Subscribing on the UI Thread
// ea.GetEvent<SimpleMessageEvent>().Subscribe(ShowMessage, ThreadOption.UIThread);
}
public void ShowMessage(string payload)
{
// TODO
}
|
发布消息
1
| eventAggregator.GetEvent<SimpleMessageEvent>().Publish("Hello!");
|
筛选订阅
1
| ea.GetEvent<SimpleMessageEvent>().Subscribe(ShowMessage, ThreadOption.UIThread, keepSubscriberReferenceAlive, x => x.Contains(" "));
|
取消订阅
1
| eventAggregator.GetEvent<SimpleMessageEvent>().Unsubscribe(ShowMessage);
|
RegionManager#
1
2
3
4
5
6
7
8
9
| <Window x:Class="Regions.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
Title="Shell">
<Grid>
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
</Grid>
</Window>
|
1
2
3
| // IContainerProvider containerProvider
var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));
|
1
2
3
4
5
6
7
| // IContainerProvider containerProvider
var regionManager = containerProvider.Resolve<IRegionManager>();
var region = regionManager.Regions["ContentRegion"];
region.Add(containerProvider.Resolve<ViewA>());
region.Add(containerProvider.Resolve<ViewB>());
region.Add(containerProvider.Resolve<ViewC>());
|
RegionNavigation#
1
2
| // IRegionManager regionManager
regionManager.RequestNavigate(regionName: "NavigateRegion", source: "Page1");
|
Navigation Callback
1
2
3
4
5
6
7
| // IRegionManager regionManager
regionManager.RequestNavigate(regionName: "NavigateRegion", source: "Page1", navigationCallback: NavigationComplete);
private void NavigationComplete(NavigationResult result)
{
dialogService.ShowDialog("NotificationDialog", new DialogParameters($"message=Navigate to {result.Context.Uri} complete."), null);
}
|
Navigation Parameters
1
2
3
4
5
6
| var parameters = new NavigationParameters
{
{ "content", "Hello!" }
};
// IRegionManager regionManager
regionManager.RequestNavigate(regionName: "NavigateRegion", source: "Page1", navigationParameters: parameters);
|
INavigationAware
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| public class Page1ViewModel : BindableBase, INavigationAware
{
...
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
if (navigationContext.Parameters["content"] is string content)
{
// TODO
}
}
...
}
|
IConfirmNavigationRequest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| public class Page1ViewModel : BindableBase, IConfirmNavigationRequest
{
...
public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
{
bool result = true;
ButtonResult buttonResult = ButtonResult.None;
dialogService.ShowDialog("NotificationDialog",
new DialogParameters($"message=Do you to navigate?"),
res => { buttonResult = res.Result; });
if (buttonResult != ButtonResult.OK)
result = false;
continuationCallback(result);
}
...
}
|
IRegionMemberLifetime
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| public class Page1ViewModel : BindableBase, INavigationAware, IRegionMemberLifetime
{
public bool KeepAlive
{
get
{
return false;
}
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return false;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
}
}
|
Navigation Journal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| public class Page1ViewModel : BindableBase, INavigationAware
{
private IRegionNavigationJournal journal;
public DelegateCommand GoForwardCommand { get; }
public DelegateCommand GoBackCommand { get; }
public Page1ViewModel()
{
GoForwardCommand = new DelegateCommand(GoForward, CanGoForward);
GoBackCommand = new DelegateCommand(GoBack);
}
...
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
journal = navigationContext.NavigationService.Journal;
GoForwardCommand.RaiseCanExecuteChanged();
}
...
private bool CanGoForward()
{
return journal != null && journal.CanGoForward;
}
private void GoForward()
{
journal?.GoForward();
}
private void GoBack()
{
journal?.GoBack();
}
}
|
DialogService#
See DOC. Dialog Service
1
2
3
4
5
6
| // DialogServiceModule.cs
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialog<NotificationDialog, NotificationDialogViewModel>();
// containerRegistry.RegisterDialogWindow<MyRibbonWindow>();
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| // viewmodel
private readonly IDialogService dialogService;
public MainViewModel(IDialogService dialogService)
{
this.dialogService = dialogService;
}
private void NavigationComplete(NavigationResult result)
{
// Show Dialog with parameters.
dialogService.ShowDialog("NotificationDialog", new DialogParameters($"message=Navigate to {result.Context.Uri} complete."), null);
}
|