WPF Prism module IModuleCatalog Add Module
Install-Package Prism.Unity;
Install-Package Prism.Wpf;
//D:\C\WpfApp20\WpfApp20\App.xaml <prism:PrismApplication x:Class="WpfApp20.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApp20" xmlns:prism="http://prismlibrary.com/"> <prism:PrismApplication.Resources> </prism:PrismApplication.Resources> </prism:PrismApplication> //D:\C\WpfApp20\WpfApp20\App.xaml.cs using CustomerModule.Services; using CustomerModule.ViewModels; using CustomerModule.Views; using OrderModule.ViewModels; using OrderModule.Views; using System.Windows; namespace WpfApp20 { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : PrismApplication { protected override Window CreateShell() { return Container.Resolve<MainWindow>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.Register<ICustomerService, CustomerService>(); containerRegistry.RegisterForNavigation<OrderListView, OrderListViewModel>(); containerRegistry.RegisterForNavigation<CustomerListView, CustomerListViewModel>(); containerRegistry.RegisterForNavigation<CustomerDetailView, CustomerDetailViewModel>(); containerRegistry.RegisterForNavigation<MainWindow, MainWindowViewModel>(); } protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) { base.ConfigureModuleCatalog(moduleCatalog); moduleCatalog.AddModule<CustomerModule.CustomerModule>(); moduleCatalog.AddModule<OrderModule.OrderModule>(); } } }







//D:\C\WpfApp20\WpfApp20\App.xaml <prism:PrismApplication x:Class="WpfApp20.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApp20" xmlns:prism="http://prismlibrary.com/"> <prism:PrismApplication.Resources> </prism:PrismApplication.Resources> </prism:PrismApplication> //D:\C\WpfApp20\WpfApp20\App.xaml.cs using CustomerModule.Services; using CustomerModule.ViewModels; using CustomerModule.Views; using OrderModule.ViewModels; using OrderModule.Views; using System.Windows; namespace WpfApp20 { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : PrismApplication { protected override Window CreateShell() { return Container.Resolve<MainWindow>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.Register<ICustomerService, CustomerService>(); containerRegistry.RegisterForNavigation<OrderListView, OrderListViewModel>(); containerRegistry.RegisterForNavigation<CustomerListView, CustomerListViewModel>(); containerRegistry.RegisterForNavigation<CustomerDetailView, CustomerDetailViewModel>(); containerRegistry.RegisterForNavigation<MainWindow, MainWindowViewModel>(); } protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) { base.ConfigureModuleCatalog(moduleCatalog); moduleCatalog.AddModule<CustomerModule.CustomerModule>(); moduleCatalog.AddModule<OrderModule.OrderModule>(); } } } //D:\C\WpfApp20\WpfApp20\MainWindow.xaml <Window x:Class="WpfApp20.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp20" mc:Ignorable="d" WindowState="Maximized" xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True" Title="MainWindow" Height="450" Width="800"> <Window.Resources> <Style TargetType="Button"> <Setter Property="FontSize" Value="50"/> </Style> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Orientation="Horizontal" Background="LightGray"> <Button Content="Customers" Command="{Binding NavigateCommand}" CommandParameter="CustomerListView"/> <Button Content="Orders" Command="{Binding NavigateCommand}" CommandParameter="OrderListView"/> </StackPanel> <ContentControl Grid.Row="1" prism:RegionManager.RegionName="MainRegion"/> </Grid> </Window> //D:\C\WpfApp20\WpfApp20\MainWindowViewModel.cs namespace WpfApp20 { public class MainWindowViewModel : BindableBase { private readonly IRegionManager regionManager; private string title = "Prism Modular Application"; public string Title { get { return title; } set { SetProperty(ref title, value); } } public DelegateCommand<string> NavigateCommand { get; set; } public MainWindowViewModel(IRegionManager regionManagerValue) { regionManager = regionManagerValue; NavigateCommand = new DelegateCommand<string>(NaviagetCommandExecuted); } private void NaviagetCommandExecuted(string viewName) { if (!string.IsNullOrEmpty(viewName)) { regionManager.RequestNavigate("MainRegion", viewName); } } } } //Customer Modules //D:\C\WpfApp20\CustomerModule\Models\Customer.cs using System; using System.Collections.Generic; using System.Text; namespace CustomerModule.Models { public class Customer { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Email { get; set; } public string Phone { get; set; } public bool IsActive { get; set; } public string FullName => $"{FirstName} {LastName}"; } } //D:\C\WpfApp20\CustomerModule\Services\CustomerService.cs using CustomerModule.Models; using System; using System.Collections.Generic; using System.Text; namespace CustomerModule.Services { public interface ICustomerService { Task<List<Customer>> GetCustomersAsync(); Task<Customer> GetCustomerByIdAsync(int id); Task AddCustomerAsync(Customer customer); Task UpdateCustomerAsync(Customer customer); Task DeleteCustomerAsync(int id); } public class CustomerService : ICustomerService { private static List<Customer> customers; static CustomerService() { customers = new List<Customer> { new Customer { Id = 1, FirstName = "John", LastName = "Doe", Email = "john.doe@email.com", Phone = "123-456-7890", IsActive = true }, new Customer { Id = 2, FirstName = "Jane", LastName = "Smith", Email = "jane.smith@email.com", Phone = "123-456-7891", IsActive = true }, new Customer { Id = 3, FirstName = "Bob", LastName = "Johnson", Email = "bob.johnson@email.com", Phone = "123-456-7892", IsActive = false } }; } public CustomerService() { } public Task AddCustomerAsync(Customer customer) { customer.Id = customers.Max(x => x.Id) + 1; customers.Add(customer); return Task.CompletedTask; } public Task DeleteCustomerAsync(int id) { var customer = customers.FirstOrDefault(x => x.Id == id); if (customer != null) { customers.Remove(customer); } return Task.CompletedTask; } public Task<Customer> GetCustomerByIdAsync(int id) { var customer = customers.FirstOrDefault(x => x.Id == id); return Task.FromResult(customer); } public Task<List<Customer>> GetCustomersAsync() { return Task.FromResult(customers); } public Task UpdateCustomerAsync(Customer customer) { int idx = -1; foreach(var c in customers) { ++idx; if(c==customer) { break; } } var existingCustomer = customers.FirstOrDefault(x => x.Id == customer.Id); if (existingCustomer != null&& idx>=0 && idx<customers.Count) { int existedIndex = idx; customers.RemoveAt(existedIndex); customers.Insert(existedIndex,customer); customers.Add(customer); } return Task.CompletedTask; } } } //D:\C\WpfApp20\CustomerModule\ViewModels\CustomerDetailViewModel.cs using CustomerModule.Models; using CustomerModule.Services; namespace CustomerModule.ViewModels { public class CustomerDetailViewModel : BindableBase, INavigationAware { private readonly ICustomerService customerService; private readonly IRegionManager regionManager; private Customer customer; private bool isEditMode; private int customerId; public Customer Customer { get => customer; set => SetProperty(ref customer, value); } public bool IsEditMode { get => isEditMode; set => SetProperty(ref isEditMode, value); } public DelegateCommand SaveCommand { get; } public DelegateCommand CancelCommand { get; } public CustomerDetailViewModel(ICustomerService customerService, IRegionManager regionManager) { this.customerService = customerService; this.regionManager = regionManager; SaveCommand = new DelegateCommand(OnSave); CancelCommand = new DelegateCommand(OnCancel); } private async void OnSave() { if (IsEditMode) { await customerService.UpdateCustomerAsync(Customer); } else { await customerService.AddCustomerAsync(Customer); } // Navigate back to customer list regionManager.RequestNavigate("MainRegion", "CustomerListView"); } private void OnCancel() { // Navigate back to customer list regionManager.RequestNavigate("MainRegion", "CustomerListView"); } // INavigationAware implementation public async void OnNavigatedTo(NavigationContext navigationContext) { if (navigationContext.Parameters.ContainsKey("customerId")) { customerId = navigationContext.Parameters.GetValue<int>("customerId"); Customer = await customerService.GetCustomerByIdAsync(customerId); IsEditMode = navigationContext.Parameters.GetValue<bool>("isEditMode"); } else { Customer = new Customer { IsActive = true }; IsEditMode = false; } } public bool IsNavigationTarget(NavigationContext navigationContext) => true; public void OnNavigatedFrom(NavigationContext navigationContext) { } } } //D:\C\WpfApp20\CustomerModule\ViewModels\CustomerListViewModel.cs using CustomerModule.Models; using CustomerModule.Services; using System.Collections.ObjectModel; using System.Windows.Input; namespace CustomerModule.ViewModels { public class CustomerListViewModel : BindableBase, INavigationAware { private readonly ICustomerService customerService; private readonly IRegionManager regionManager; private ObservableCollection<Customer> customers; private Customer selectedCustomer; public ObservableCollection<Customer> Customers { get => customers; set => SetProperty(ref customers, value); } public Customer SelectedCustomer { get => selectedCustomer; set => SetProperty(ref selectedCustomer, value); } public ICommand AddCustomerCommand { get; } public ICommand EditCustomerCommand { get; } public ICommand DeleteCustomerCommand { get; } public ICommand ViewDetailsCommand { get; } public CustomerListViewModel(ICustomerService customerService, IRegionManager regionManager) { this.customerService = customerService; this.regionManager = regionManager; AddCustomerCommand = new DelegateCommand(OnAddCustomer); EditCustomerCommand = new DelegateCommand(OnEditCustomer, CanEditCustomer) .ObservesProperty(() => SelectedCustomer); DeleteCustomerCommand = new DelegateCommand(OnDeleteCustomer, CanDeleteCustomer) .ObservesProperty(() => SelectedCustomer); ViewDetailsCommand = new DelegateCommand(OnViewDetails, CanViewDetails) .ObservesProperty(() => SelectedCustomer); LoadCustomers(); } private async void LoadCustomers() { var customers = await customerService.GetCustomersAsync(); Customers = new ObservableCollection<Customer>(customers); } private void OnAddCustomer() { var parameters = new NavigationParameters(); regionManager.RequestNavigate("MainRegion", "CustomerDetailView", parameters); LoadCustomers(); } private void OnEditCustomer() { if (SelectedCustomer != null) { var parameters = new NavigationParameters { { "customerId", SelectedCustomer.Id }, { "isEditMode", true } }; regionManager.RequestNavigate("MainRegion", "CustomerDetailView", parameters); } } private bool CanEditCustomer() => SelectedCustomer != null; private async void OnDeleteCustomer() { if (SelectedCustomer != null) { await customerService.DeleteCustomerAsync(SelectedCustomer.Id); LoadCustomers(); } } private bool CanDeleteCustomer() => SelectedCustomer != null; private void OnViewDetails() { if (SelectedCustomer != null) { var parameters = new NavigationParameters { { "customerId", SelectedCustomer.Id } }; regionManager.RequestNavigate("MainRegion", "CustomerDetailView", parameters); } } private bool CanViewDetails() => SelectedCustomer != null; // INavigationAware implementation public void OnNavigatedTo(NavigationContext navigationContext) { // Refresh data when navigated to LoadCustomers(); } public bool IsNavigationTarget(NavigationContext navigationContext) => true; public void OnNavigatedFrom(NavigationContext navigationContext) { } } } //D:\C\WpfApp20\CustomerModule\Views\CustomerDetailView.xaml <UserControl x:Class="CustomerModule.Views.CustomerDetailView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:CustomerModule.Views" xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"> <Grid Margin="20" Width="400"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <TextBlock Grid.Row="0" Grid.ColumnSpan="2" Text="{Binding IsEditMode, StringFormat={}{0:Edit Customer:Add New Customer}}" FontSize="16" FontWeight="Bold" Margin="0,0,0,10"/> <TextBlock Grid.Row="1" Grid.Column="0" Text="First Name:" Margin="0,0,10,5"/> <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Customer.FirstName}" Margin="0,0,0,5"/> <TextBlock Grid.Row="2" Grid.Column="0" Text="Last Name:" Margin="0,0,10,5"/> <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Customer.LastName}" Margin="0,0,0,5"/> <TextBlock Grid.Row="3" Grid.Column="0" Text="Email:" Margin="0,0,10,5"/> <TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Customer.Email}" Margin="0,0,0,5"/> <TextBlock Grid.Row="4" Grid.Column="0" Text="Phone:" Margin="0,0,10,5"/> <TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Customer.Phone}" Margin="0,0,0,5"/> <CheckBox Grid.Row="5" Grid.Column="1" Content="Active" IsChecked="{Binding Customer.IsActive}" Margin="0,0,0,10"/> <StackPanel Grid.Row="8" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Right"> <Button Content="Save" Command="{Binding SaveCommand}" Margin="0,0,10,0" Padding="15,5"/> <Button Content="Cancel" Command="{Binding CancelCommand}" Padding="15,5"/> </StackPanel> </Grid> </UserControl> //D:\C\WpfApp20\CustomerModule\Views\CustomerListView.xaml <UserControl x:Class="CustomerModule.Views.CustomerListView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:CustomerModule.Views" mc:Ignorable="d" xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!-- Toolbar --> <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0,0,0,10"> <Button Content="Add Customer" Command="{Binding AddCustomerCommand}" Margin="0,0,10,0" Padding="10,5"/> <Button Content="Edit" Command="{Binding EditCustomerCommand}" Margin="0,0,10,0" Padding="10,5"/> <Button Content="Delete" Command="{Binding DeleteCustomerCommand}" Margin="0,0,10,0" Padding="10,5"/> <Button Content="View Details" Command="{Binding ViewDetailsCommand}" Padding="10,5"/> </StackPanel> <!-- Customers List --> <DataGrid Grid.Row="1" ItemsSource="{Binding Customers}" SelectedItem="{Binding SelectedCustomer}" AutoGenerateColumns="False" IsReadOnly="True" FontSize="30"> <DataGrid.Columns> <DataGridTextColumn Header="ID" Binding="{Binding Id}" Width="Auto"/> <DataGridTextColumn Header="First Name" Binding="{Binding FirstName}" Width="*"/> <DataGridTextColumn Header="Last Name" Binding="{Binding LastName}" Width="*"/> <DataGridTextColumn Header="Email" Binding="{Binding Email}" Width="*"/> <DataGridCheckBoxColumn Header="Active" Binding="{Binding IsActive}" Width="Auto"/> </DataGrid.Columns> </DataGrid> </Grid> </UserControl> //D:\C\WpfApp20\CustomerModule\CustomerModule.cs using CustomerModule.Views; namespace CustomerModule { public class CustomerModule : IModule { private readonly IRegionManager regionManager; public CustomerModule(IRegionManager regionManagerValue) { regionManager= regionManagerValue; } public void OnInitialized(IContainerProvider containerProvider) { regionManager.RegisterViewWithRegion("MainRegion", typeof(CustomerListView)); } public void RegisterTypes(IContainerRegistry containerRegistry) { } } } //OrderModule //D:\C\WpfApp20\OrderModule\OrderModule.cs using OrderModule.Views; using System; using System.Collections.Generic; using System.Text; namespace OrderModule { public class OrderModule : IModule { private readonly IRegionManager regionManager; public OrderModule(IRegionManager regionManagerValue) { regionManager = regionManagerValue; } public void OnInitialized(IContainerProvider containerProvider) { // Module initialization regionManager.RegisterViewWithRegion("MainRegion", typeof(OrderListView)); } public void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterForNavigation<OrderListView>(); } } } //D:\C\WpfApp20\OrderModule\Views\OrderListView.xaml <UserControl x:Class="OrderModule.Views.OrderListView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:OrderModule.Views" xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"> <Grid> <TextBlock Text="{Binding OrderTitle}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="50" FontWeight="Bold"/> </Grid> </UserControl> //D:\C\WpfApp20\OrderModule\ViewModels\OrderListViewModel.cs using System; using System.Collections.Generic; using System.Text; namespace OrderModule.ViewModels { public class OrderListViewModel : BindableBase { public OrderListViewModel() { OrderTitle = $"In Order View\nnow is {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"; System.Timers.Timer tmr=new System.Timers.Timer(); tmr.Interval = 1000; tmr.Elapsed += Tmr_Elapsed; tmr.Start(); } private void Tmr_Elapsed(object? sender, System.Timers.ElapsedEventArgs e) { OrderTitle = $"In Order View\nnow is {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"; } private string orderTitle; public string OrderTitle { get { return orderTitle; } set { SetProperty(ref orderTitle, value); } } } }
These are universal concepts in Dependency Injection.
| Lifetime | Description | Simple Analogy |
|---|---|---|
| Transient | A new instance is created every time it is requested from the container. | Like a Coffee-To-Go. You get a fresh, disposable cup every time you order. |
| Singleton | A single instance is created for the entire application lifetime and shared across all requests. | The Office Coffee Pot. There's one pot that everyone shares. If you drink the last cup, it's empty for everyone. |
| Scoped | A single instance is created and shared per "scope". In web contexts, a scope is often a single HTTP request. In WPF/Prism, you typically create scopes manually for specific purposes, like per-navigation event. | A Meeting's Water Pitcher. A new pitcher is brought in for each new meeting (scope) and shared by all attendees of that meeting. |
| Instance | You create an object yourself and register that specific instance with the container. The container will always return this exact instance. It behaves like a singleton you pre-made. | A Bottled Drink. You bring a specific, pre-made bottle (the instance) and the container just hands it out. |

浙公网安备 33010602011771号