Install-Package Prism.DryIOC;
Install-Package Prism.Wpf;
//BookModule using BookModule.Services; using BookModule.ViewModels; using BookModule.Views; using System; using System.Collections.Generic; using System.Text;namespace BookModule {public class BookModule : IModule{private IRegionManager regionManager;public BookModule(IRegionManager regionManagerValue){regionManager = regionManagerValue;}public void OnInitialized(IContainerProvider containerProvider){regionManager.RegisterViewWithRegion("BooksRegion", typeof(BookView));}public void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<IIDService, IDService>();containerRegistry.Register<INameService, NameService>();containerRegistry.Register<IISBNService, ISBNService>();containerRegistry.RegisterForNavigation<BookView, BookViewViewModel>("BookView");}} }//UserModule using System; using System.Collections.Generic; using System.Text; using UserModule.ViewModels; using UserModule.Views;namespace UserModule {public class UserModule : IModule{IRegionManager regionManager;public UserModule(IRegionManager regionManagerValue){regionManager = regionManagerValue;}public void OnInitialized(IContainerProvider containerProvider){//regionManager.RegisterViewWithRegion("UserRegion",typeof(UserView)); }public void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.RegisterForNavigation<UserView, UserViewModel>("UserView");}} }//App.xaml.cs using BookModule; using BookModule.Services; using BookModule.ViewModels; using BookModule.Views; using Prism.Commands; using Prism.Ioc; using Prism.Modularity; using System.Configuration; using System.Data; using System.Windows; using UserModule; using UserModule.ViewModels; using UserModule.Views;namespace WpfApp22 {/// <summary>/// Interaction logic for App.xaml/// </summary>public partial class App : PrismApplication{protected override Window CreateShell(){return Container.Resolve<ShellView>();}protected override void OnInitialized(){base.OnInitialized();var regionManager = Container.Resolve<IRegionManager>();regionManager.RequestNavigate("BookRegion", "BookView");regionManager.RequestNavigate("UserRegion", "UserView");}protected override void RegisterTypes(IContainerRegistry containerRegistry){ containerRegistry.RegisterForNavigation<ShellView, ShellViewModel>();}protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog){base.ConfigureModuleCatalog(moduleCatalog);moduleCatalog.AddModule<BookModule.BookModule>();moduleCatalog.AddModule<UserModule.UserModule>();}}}
using System; using System.Collections.Generic; using System.Text;namespace BookModule.Models {public class StatusUpdatedEvent : PubSubEvent<string>{} }public class BookViewViewModel : BindableBase {IIDService idService;IISBNService isbnService;INameService nameService;IEventAggregator eventAggregator;public BookViewViewModel(IIDService idServiceValue, IISBNService isbnServiceValue,INameService nameServiceValue, IEventAggregator eventAggregatorValue){idService = idServiceValue;isbnService = isbnServiceValue;nameService = nameServiceValue;eventAggregator = eventAggregatorValue;}public void UpdateMainStatus(string mainStatusValue){eventAggregator.GetEvent<StatusUpdatedEvent>().Publish(mainStatusValue);} }public class ShellViewModel : BindableBase {private IEventAggregator eventAggregator;public ShellViewModel(IEventAggregator eventAggregatorValue){eventAggregator = eventAggregatorValue;eventAggregator.GetEvent<StatusUpdatedEvent>().Subscribe(OnStatusUpdated);MainStatus = "Loading...";MainStr = $"In Main view,now 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 OnStatusUpdated(string statusValue){MainStatus = statusValue;}public void OnUnload(){eventAggregator.GetEvent<StatusUpdatedEvent>().Unsubscribe(OnStatusUpdated);} }
//Main //App.xaml <prism:PrismApplication x:Class="WpfApp22.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:WpfApp22"xmlns:prism="http://prismlibrary.com/"> </prism:PrismApplication>//App.xaml.cs using BookModule; using BookModule.Services; using BookModule.ViewModels; using BookModule.Views; using Prism.Commands; using Prism.Ioc; using Prism.Modularity; using System.Configuration; using System.Data; using System.Windows; using UserModule; using UserModule.ViewModels; using UserModule.Views;namespace WpfApp22 {/// <summary>/// Interaction logic for App.xaml/// </summary>public partial class App : PrismApplication{protected override Window CreateShell(){return Container.Resolve<ShellView>();}protected override void OnInitialized(){base.OnInitialized();var regionManager = Container.Resolve<IRegionManager>();regionManager.RequestNavigate("BookRegion", "BookView");regionManager.RequestNavigate("UserRegion", "UserView");}protected override void RegisterTypes(IContainerRegistry containerRegistry){ containerRegistry.RegisterForNavigation<ShellView, ShellViewModel>();}protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog){base.ConfigureModuleCatalog(moduleCatalog);moduleCatalog.AddModule<BookModule.BookModule>();moduleCatalog.AddModule<UserModule.UserModule>();}}}//MainWindow.xaml <Window x:Class="WpfApp22.ShellView"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:prism="http://prismlibrary.com/"prism:ViewModelLocator.AutoWireViewModel="True"WindowState="Maximized"HorizontalAlignment="Stretch"VerticalAlignment="Stretch"xmlns:local="clr-namespace:WpfApp22"mc:Ignorable="d"Title="ShellView" Height="450" Width="800"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="*"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"Text="{Binding MainStr}" FontSize="50" /><ContentControl prism:RegionManager.RegionName="BookRegion"Grid.Row="1"Grid.Column="0"VerticalAlignment="Stretch"HorizontalAlignment="Stretch"/><ContentControl prism:RegionManager.RegionName="UserRegion"Grid.Row="1"Grid.Column="1"VerticalAlignment="Stretch"HorizontalAlignment="Stretch"/><TextBlock Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"Text="{Binding MainStatus}" FontSize="50" /></Grid> </Window>//MainViewModel.cs using BookModule.Models; using BookModule.ViewModels; using System; using System.Collections.Generic; using System.Text;namespace WpfApp22 {public class ShellViewModel : BindableBase{private IEventAggregator eventAggregator;public ShellViewModel(IEventAggregator eventAggregatorValue){eventAggregator = eventAggregatorValue;eventAggregator.GetEvent<StatusUpdatedEvent>().Subscribe(OnStatusUpdated);MainStatus = "Loading...";MainStr = $"In Main view,now 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 OnStatusUpdated(string statusValue){MainStatus = statusValue;}public void OnUnload(){eventAggregator.GetEvent<StatusUpdatedEvent>().Unsubscribe(OnStatusUpdated);}private void Tmr_Elapsed(object? sender, System.Timers.ElapsedEventArgs e){MainStr = $"In Main view,now is {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}";}private string mainStr;public string MainStr{get{return mainStr;}set{SetProperty(ref mainStr, value);}}private string mainStatus;public string MainStatus{get{return mainStatus;}set{SetProperty(ref mainStatus, value);}}public Action<string> UpdateMainStatusAction => UpdateMainStatus;private void UpdateMainStatus(string statusValue){MainStatus = statusValue;}} }//ModuleA using System; using System.Collections.Generic; using System.Text; using System.Windows.Media;namespace BookModule.Models {public class Book{public int Id { get; set; }public string Name { get; set; }public string Author { get; set; }public string Title { get; set; }public string Topic { get; set; }public string ISBN { get; set; }public ImageSource ImgSource { get; set; }} }using System; using System.Collections.Generic; using System.Text;namespace BookModule.Models {public class StatusUpdatedEvent : PubSubEvent<string>{} }using System; using System.Collections.Generic; using System.Text;namespace BookModule.Services {public interface IIDService{int GetID();}public class IDService:IIDService{int id = 0;public int GetID(){return Interlocked.Increment(ref id);}} }using System; using System.Collections.Generic; using System.Text;namespace BookModule.Services {public interface IISBNService{string GetISBN();}public class ISBNService : IISBNService{int idx = 0;public string GetISBN(){return $"ISBN_{Interlocked.Increment(ref idx)}_{Guid.NewGuid():N}";}} } using System; using System.Collections.Generic; using System.Text;namespace BookModule.Services {public interface INameService{string GetName();}public class NameService:INameService{int idx = 0;public string GetName(){return $"Name_{++idx}";}} } using BookModule.Models; using BookModule.Services; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Text; using System.Windows.Media; using System.Windows.Media.Imaging;namespace BookModule.ViewModels {public class BookViewViewModel : BindableBase{IIDService idService;IISBNService isbnService;INameService nameService;IEventAggregator eventAggregator;public BookViewViewModel(IIDService idServiceValue, IISBNService isbnServiceValue,INameService nameServiceValue, IEventAggregator eventAggregatorValue){idService = idServiceValue;isbnService = isbnServiceValue;nameService = nameServiceValue;eventAggregator = eventAggregatorValue;}public void UpdateMainStatus(string mainStatusValue){eventAggregator.GetEvent<StatusUpdatedEvent>().Publish(mainStatusValue);}public async Task InitBooksCollection(){var imgDir = @"D:\C\WpfApp22\BookModule\Images\";if (!Directory.Exists(imgDir)){return;}var imgs = Directory.GetFiles(imgDir);if (imgs == null || !imgs.Any()){return;}int imgsCount = imgs.Count();BooksCollection = new ObservableCollection<Book>();List<Book> booksList = new List<Book>();await Task.Run(async () =>{for (int i = 1; i < 1000001; i++){booksList.Add(new Book(){Id = idService.GetID(),Name = nameService.GetName(),ISBN = isbnService.GetISBN(),Title = $"Title_{i}",Topic = $"Topic_{i}",Author = $"Author_{i}",ImgSource = GetImgSourceViaUrl(imgs[i % imgsCount])});if (i % 1000 == 0){await PopulateBooksCollectionAsync(booksList);}}if (booksList.Any()){await PopulateBooksCollectionAsync(booksList);}});}private async Task PopulateBooksCollectionAsync(List<Book> booksList){var tempList = booksList.ToList();booksList.Clear();await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>{foreach (var bk in tempList){BooksCollection.Add(bk);}UpdateMainStatus($"Loaded {BooksCollection.Count} items!");}, System.Windows.Threading.DispatcherPriority.Background);}private ImageSource GetImgSourceViaUrl(string imgUrl){BitmapImage bmi = new BitmapImage();bmi.BeginInit();bmi.UriSource = new Uri(imgUrl, UriKind.RelativeOrAbsolute);bmi.EndInit();bmi.Freeze();return bmi;}private ObservableCollection<Book> booksCollection;public ObservableCollection<Book> BooksCollection{get{return booksCollection;}set{SetProperty(ref booksCollection, value);}}private double gridWidth;public double GridWidth{get{return gridWidth;}set{SetProperty(ref gridWidth, value);}}private double gridHeight;public double GridHeight{get{return gridHeight;}set{SetProperty(ref gridHeight, value);}}} } <UserControl x:Class="BookModule.Views.BookView"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:BookModule.Views"xmlns:prism="http://prismlibrary.com/"VerticalAlignment="Stretch"HorizontalAlignment="Stretch"prism:ViewModelLocator.AutoWireViewModel="True"><Grid><ListBox ItemsSource="{Binding BooksCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"VirtualizingPanel.IsVirtualizing="True"VirtualizingPanel.VirtualizationMode="Recycling"VirtualizingPanel.CacheLength="2,2"VirtualizingPanel.CacheLengthUnit="Item"ScrollViewer.IsDeferredScrollingEnabled="True"ScrollViewer.CanContentScroll="True"><ListBox.ItemTemplate><DataTemplate><Grid Width="{Binding DataContext.GridWidth,RelativeSource={RelativeSource AncestorType=UserControl}}"Height="{Binding DataContext.GridHeight,RelativeSource={RelativeSource AncestorType=UserControl}}"><Grid.Background><ImageBrush ImageSource="{Binding ImgSource}"Stretch="UniformToFill"/></Grid.Background><Grid.Resources><Style TargetType="{x:Type TextBlock}"><Setter Property="HorizontalAlignment" Value="Center"/><Setter Property="VerticalAlignment" Value="Center"/><Setter Property="FontSize" Value="20"/><Style.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter Property="FontSize" Value="30"/><Setter Property="Foreground" Value="Red"/></Trigger></Style.Triggers></Style></Grid.Resources><Grid.RowDefinitions><RowDefinition/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Id}"/><TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Name}"/><TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding Author}"/><TextBlock Grid.Row="0" Grid.Column="3" Text="{Binding Title}"/><TextBlock Grid.Row="0" Grid.Column="4" Text="{Binding Topic}"/><TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="5" Text="{Binding ISBN}"/></Grid></DataTemplate></ListBox.ItemTemplate></ListBox></Grid> </UserControl>using BookModule.ViewModels; using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes;namespace BookModule.Views {/// <summary>/// Interaction logic for BookView.xaml/// </summary>public partial class BookView : UserControl{public BookView(){InitializeComponent();this.SizeChanged += (s, e) =>{if (this.DataContext is BookViewViewModel bkVM){bkVM.GridWidth = this.ActualWidth;bkVM.GridHeight = this.ActualHeight;}};this.Loaded += async (s, e) =>{if (this.DataContext is BookViewViewModel bkVM){await bkVM.InitBooksCollection();}};}private async Task BookView_Loaded(object sender, RoutedEventArgs e){}} } using BookModule.Services; using BookModule.ViewModels; using BookModule.Views; using System; using System.Collections.Generic; using System.Text;namespace BookModule {public class BookModule : IModule{private IRegionManager regionManager;public BookModule(IRegionManager regionManagerValue){regionManager = regionManagerValue;}public void OnInitialized(IContainerProvider containerProvider){regionManager.RegisterViewWithRegion("BooksRegion", typeof(BookView));}public void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<IIDService, IDService>();containerRegistry.Register<INameService, NameService>();containerRegistry.Register<IISBNService, ISBNService>();containerRegistry.RegisterForNavigation<BookView, BookViewViewModel>("BookView");}} }//Module B using System; using System.Collections.Generic; using System.Text;namespace UserModule.Models {public class User{public int Id { get; set; } public string Name { get; set; }public string Email { get; set; }} }using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics.Eventing.Reader; using System.IO; using System.Text; using System.Windows.Controls; using UserModule.Models;namespace UserModule.ViewModels {public class UserViewModel : BindableBase{public UserViewModel(){InitUsersCollection();SaveInExcelCommand = new DelegateCommand<object>(SaveInExcelCommandExecuted);}private void SaveInExcelCommandExecuted(object obj){var dg = obj as DataGrid;if (dg != null){var items = dg.ItemsSource?.Cast<User>()?.ToList();}}private void InitUsersCollection(){UsersCollection = new ObservableCollection<User>();for (int i = 1; i < 1001; i++){UsersCollection.Add(new User(){Id = i * i,Name = $"Name_{i}",Email = $"User_{i}@gmail.com"});}}private ObservableCollection<User> usersCollection;public ObservableCollection<User> UsersCollection{get{return usersCollection;}set{SetProperty(ref usersCollection, value);}}public DelegateCommand<object> SaveInExcelCommand { get; set; }public void ExportListTAsExcel<T>(List<T> dataList, string filePath = "", string sheetName = "Sheet1"){if (dataList == null || !dataList.Any()){return;}//// Set EPPlus license context for free use//ExcelPackage.LicenseContext = LicenseContext.NonCommercial;//using (var package = new ExcelPackage())//{// var worksheet = package.Workbook.Worksheets.Add(sheetName);// // Load data starting from cell A1// worksheet.Cells["A1"].LoadFromCollection(dataList, true);// // Auto-fit columns for better readability// worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();// // Save the file// package.SaveAs(new FileInfo(filePath));//} }}}<UserControl x:Class="UserModule.Views.UserView"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:UserModule.Views"xmlns:prism="http://prismlibrary.com/"prism:ViewModelLocator.AutoWireViewModel="True"VerticalAlignment="Stretch"HorizontalAlignment="Stretch"><Grid><DataGrid ItemsSource="{Binding UsersCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"VirtualizingPanel.IsVirtualizing="True"VirtualizingPanel.VirtualizationMode="Recycling"VirtualizingPanel.CacheLength="2,2"VirtualizingPanel.CacheLengthUnit="Item"ScrollViewer.IsDeferredScrollingEnabled="True"ScrollViewer.CanContentScroll="True"FontSize="50"><DataGrid.ContextMenu><ContextMenu><MenuItem Header="Save In Excel"Command="{Binding SaveInExcelCommand}"CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu},Path=PlacementTarget}"/></ContextMenu></DataGrid.ContextMenu></DataGrid></Grid> </UserControl>using System; using System.Collections.Generic; using System.Text; using UserModule.ViewModels; using UserModule.Views;namespace UserModule {public class UserModule : IModule{IRegionManager regionManager;public UserModule(IRegionManager regionManagerValue){regionManager = regionManagerValue;}public void OnInitialized(IContainerProvider containerProvider){//regionManager.RegisterViewWithRegion("UserRegion",typeof(UserView)); }public void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.RegisterForNavigation<UserView, UserViewModel>("UserView");}} }