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>();
        }
    }

}

 

 

 

image

 

 

 

 

image

 

 

image

 

 

 

 

 

 

 

 

 

 

 

image

 

 

 

 

 

 

 

 

image

 

 

 

 

 

 

 

 

 

image

 

 

image

 

 

 

 

 

 

 

 

 

 

 

 

//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.

 
LifetimeDescriptionSimple 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.
posted @ 2025-09-29 21:15  FredGrit  阅读(5)  评论(0)    收藏  举报