WPF Prism IRegionManager, IContainerRegistry implements IOC, IModule implements module management,IEventAggregator implements message broadcast via Publish,Subscribe,PubSubEvent<T>

//Install-Package for the whole solution
Get-Project -All | Install-Package Prism.Wpf;
Get-Project -All | Install-Pacjage Prism.DryIoc;

 

The whole structure as below,WpfApp29 as the start up application, other projects are all modified as  class library project

 

image

 

 

 

using BookProject;
using ImageProject;
using System.Configuration;
using System.Data;
using System.Windows;
using WpfApp29.Service;
using WpfApp29.ViewModels;

namespace WpfApp29
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : PrismApplication
    {
        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }

        protected override void OnInitialized()
        {
            base.OnInitialized();
            var regionManager = Container.Resolve<IRegionManager>();
            regionManager.RequestNavigate("MainRegion", "BookView");
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.Register<ITimeService, TimeService>();
            containerRegistry.RegisterForNavigation<MainWindow, MainWindowViewModel>();
        }

        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
        {
            base.ConfigureModuleCatalog(moduleCatalog);
            moduleCatalog.AddModule<BookModule>();
            moduleCatalog.AddModule<ImageModule>();
        }
    }

}

 

 

image

 

 

 

 

 

 

 

image

 

 

image

 

 

 

image

 

 

 

//Runtime project
using System;
using System.Collections.Generic;
using System.Text;

namespace Runtime.Common.Models
{
    public class MsgPayLoad
    {
        public int Idx { get; set; }
        public string TimeStr { get; set; }
        public string Msg { get; set; }
    }

    public class MsgPayLoadEvent : PubSubEvent<MsgPayLoad>
    {
    }
}

//BookProject
using System;
using System.Collections.Generic;
using System.Text;

namespace BookProject.Models
{
    public class Book
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string ISBN {  get; set; }
        public string Title { get; set; }
        public string Topic {  get; set; }
    }
}



using System;
using System.Collections.Generic;
using System.Text;

namespace BookProject.Services
{
    public interface IIDService
    {
        int GetID();
    }

    public class IDService : IIDService
    {
        int id = 0;

        public int GetID()
        {
            return Interlocked.Increment(ref id);
        }
    }

    public interface INameService
    {
        string GetName();
    }

    public class NameService : INameService
    {
        int idx = 0;
        public string GetName()
        {
            return $"Name_{Interlocked.Increment(ref idx)}";
        }
    }

    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 BookProject.Models;
using BookProject.Services;
using Runtime.Common.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows.Shell;

namespace BookProject.ViewModels
{
    public class BookViewModel : BindableBase
    {
        IIDService idService;
        INameService nameService;
        IISBNService isbnService;
        IEventAggregator eventAggregator;
        public BookViewModel(IIDService idServiceValue, INameService nameServiceValue,
            IISBNService isbnServiceValue,IEventAggregator eventAggregatorValue)
        {
            idService = idServiceValue;
            nameService = nameServiceValue;
            isbnService = isbnServiceValue;
            eventAggregator = eventAggregatorValue;
        }

        public async Task InitBooksCollectionAsync()
        {
            BooksCollection = new ObservableCollection<Book>();
            List<Book> booksList = new List<Book>();

            for (int i = 1; i < 10000001; i++)
            {
                booksList.Add(new Book()
                {
                    Id = idService.GetID(),
                    Name = nameService.GetName(),
                    ISBN = isbnService.GetISBN(),
                    Title = $"Title_{1}",
                    Topic = $"Topic_{i}"
                });

                if (i % 100000 == 0)
                {
                    await PopulateBooksCollectionAsync(booksList);
                }
            }

            if(booksList.Any())
            {
                await PopulateBooksCollectionAsync(booksList);
            }

            MsgPayLoad msgLoad = new MsgPayLoad()
            {
                Idx = BooksCollection.LastOrDefault().Id,
                TimeStr = $"Now:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}",
                Msg = $"Loaded {BooksCollection.Count} items finished!"
            };
            eventAggregator.GetEvent<MsgPayLoadEvent>().Publish(msgLoad);
        }

        private async Task PopulateBooksCollectionAsync(List<Book> booksList)
        {
            var tempList = booksList.ToList();
            booksList.Clear();
            await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
            {
                foreach (var book in tempList)
                {
                    BooksCollection.Add(book);
                }
                MsgPayLoad msgLoad = new MsgPayLoad()
                {
                    Idx = tempList.LastOrDefault().Id,
                    TimeStr=$"Now:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}",
                    Msg=$"Loaded {BooksCollection.Count} items"
                };
                eventAggregator.GetEvent<MsgPayLoadEvent>().Publish(msgLoad);
            }, System.Windows.Threading.DispatcherPriority.Background);
        }

        private ObservableCollection<Book> booksCollection;
        public ObservableCollection<Book> BooksCollection
        {
            get
            {
                return booksCollection;
            }
            set
            {
                SetProperty(ref booksCollection, value);
            }
        }
    }
}

<UserControl x:Class="BookProject.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:BookProject.Views"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             xmlns:prism="http://prismlibrary.com/"
             VerticalAlignment="Stretch"
             HorizontalAlignment="Stretch"
             prism:ViewModelLocator.AutoWireViewModel="True">
    <Grid>
        <DataGrid ItemsSource="{Binding BooksCollection}"
                      VirtualizingPanel.IsVirtualizing="True"
                      VirtualizingPanel.VirtualizationMode="Recycling"
                      VirtualizingPanel.CacheLength="2,2"
                      VirtualizingPanel.CacheLengthUnit="Item"
                      ScrollViewer.IsDeferredScrollingEnabled="True"
                      ScrollViewer.CanContentScroll="True"
                      AutoGenerateColumns="True"
                      CanUserAddRows="False"
                      FontSize="30"/>
    </Grid>
</UserControl>

using BookProject.ViewModels;
using System;
using System.Collections.Generic;
using System.Text;
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 BookProject.Views
{
    /// <summary>
    /// Interaction logic for BookView.xaml
    /// </summary>
    public partial class BookView : UserControl
    {
        public BookView()
        {
            InitializeComponent();
            this.Loaded += async (s, e) =>
            {
                var vm = this.DataContext as BookViewModel;
                if (vm != null)
                {
                    await vm.InitBooksCollectionAsync();
                }
            };
        }
    }
}



using BookProject.Services;
using BookProject.ViewModels;
using BookProject.Views;
using System;
using System.Collections.Generic;
using System.Text;

namespace BookProject
{
    public class BookModule : IModule
    {
        public void OnInitialized(IContainerProvider containerProvider)
        {

        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.Register<IIDService, IDService>();
            containerRegistry.Register<INameService, NameService>();
            containerRegistry.Register<IISBNService, ISBNService>();
            containerRegistry.RegisterForNavigation<BookView, BookViewModel>("BookView");
        }
    }
}


//ImageProject
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace ImageProject.Services
{
    public interface IImageService
    {
        ImageSource GetImgSourceViaUrl(string imgUrl);
    }
    public class ImageService : IImageService
    {
        private ConcurrentDictionary<string, ImageSource> imgDicCache = new ConcurrentDictionary<string, ImageSource>();
        public ImageSource GetImgSourceViaUrl(string imgUrl)
        {
            if (!File.Exists(imgUrl))
            {
                BitmapImage nullBmi = new BitmapImage();
                return nullBmi;
            }

            if (imgDicCache.TryGetValue(imgUrl, out ImageSource imgSource))
            {
                return imgSource;
            }
            BitmapImage bmi = new BitmapImage();

            bmi.BeginInit();
            bmi.UriSource = new Uri(imgUrl, UriKind.RelativeOrAbsolute);
            bmi.EndInit();
            if (bmi.CanFreeze)
            {
                bmi.Freeze();
            }
            imgDicCache[imgUrl] = bmi;
            return bmi;
        }
    }
}


using ImageProject.Services;
using Runtime.Common.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Media;

namespace ImageProject.ViewModels
{
    public class ImageViewModel:BindableBase
    {
        ImageService imageService;
        IEventAggregator eventAggregator;
        List<string> imgsUrlList = new List<string>();
        int imgsCount = 0;
        int imgIdx = 0;
        public ImageViewModel(IEventAggregator eventAggregatorValue,ImageService imageServiceValue)
        {
            eventAggregator = eventAggregatorValue;
            imageService = imageServiceValue;
        }

        public void InitImageSource()
        {
            var dir = @"Images";
            if(!Directory.Exists(dir))
            {
                return;
            }

            imgsUrlList = new List<string>(Directory.GetFiles(dir));
            if(!imgsUrlList.Any() )
            {
                return;
            }
            imgsCount = imgsUrlList.Count;
            ImgUrl = imgsUrlList[(++imgIdx) % imgsCount];
            ImgSource = imageService.GetImgSourceViaUrl(ImgUrl);
            Task.Run(() =>
            {
                InitTimer();
            });            
        }

        private void InitTimer()
        {
            System.Timers.Timer tmr = new System.Timers.Timer();
            tmr.Elapsed += Tmr_Elapsed;
            tmr.Interval = 1000;
            tmr.Start();
        }

        private void Tmr_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
        {
            System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
            {
                ImgUrl = System.IO.Path.GetFullPath(imgsUrlList[(++imgIdx) % imgsCount]);
                ImgSource = imageService.GetImgSourceViaUrl(ImgUrl);
            });
           

            MsgPayLoad msgPayLoad = new MsgPayLoad()
            {
                Idx = imgIdx,
                TimeStr = $"Now:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}",
                Msg = System.IO.Path.GetFullPath(ImgUrl)
            };
            eventAggregator.GetEvent<MsgPayLoadEvent>().Publish(msgPayLoad);
        }

        private string imgUrl;
        public string ImgUrl
        {
            get
            {
                return imgUrl; 
            }
            set
            {
                SetProperty(ref imgUrl, value);
            }
        }

        private ImageSource imgSource;
        public ImageSource ImgSource
        {
            get
            {
                return imgSource;
            }
            set
            {
                SetProperty(ref imgSource, value);
            }
        }
    }
}


<UserControl x:Class="ImageProject.Views.ImageView"
             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:ImageProject.Views"
             xmlns:prism="http://prismlibrary.com/"
             VerticalAlignment="Stretch"
             HorizontalAlignment="Stretch"
             prism:ViewModelLocator.AutoWireViewModel="True"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Grid.Background>
            <ImageBrush ImageSource="{Binding ImgSource}"
                        Stretch="Uniform"/>
        </Grid.Background>
        <TextBlock Text="{Binding ImgUrl}"
                   FontSize="30"
                   Foreground="Red"
                   TextWrapping="Wrap"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center"/>
    </Grid>
</UserControl>

using ImageProject.ViewModels;
using System;
using System.Collections.Generic;
using System.Text;
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 ImageProject.Views
{
    /// <summary>
    /// Interaction logic for ImageView.xaml
    /// </summary>
    public partial class ImageView : UserControl
    {
        public ImageView()
        {
            InitializeComponent();
            this.Loaded += async (s, e) =>
            {
                var vm = this.DataContext as ImageViewModel;
                if (vm != null)
                {
                    vm.InitImageSource();
                }
            };
        }
    }
}


using ImageProject.Services;
using ImageProject.ViewModels;
using ImageProject.Views;
using System;
using System.Collections.Generic;
using System.Text;

namespace ImageProject
{
    public class ImageModule : IModule
    {
        public void OnInitialized(IContainerProvider containerProvider)
        {
             var regionManager= containerProvider.Resolve<IRegionManager>();
             
        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.Register<IImageService, ImageService>();
            containerRegistry.RegisterForNavigation<ImageView, ImageViewModel>("ImageView");
        }
    }
}


//WpfApp29 as startup application
using System;
using System.Collections.Generic;
using System.Text;

namespace WpfApp29.Service
{
    public interface ITimeService
    {
        string GetTimeNow();
    }

    public class TimeService:ITimeService
    {
        int idx = 0;
        public string GetTimeNow()
        {
            return $"{Interlocked.Increment(ref idx)}_{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}";
        }
    }
}


using BookProject.Models;
using Prism.Events;
using Runtime.Common.Models;
using System;
using System.Collections.Generic;
using System.Text;
using WpfApp29.Service;

namespace WpfApp29.ViewModels
{
    public class MainWindowViewModel:BindableBase
    {
        ITimeService timeService;
        IContainerProvider containerProvider;
        IRegionManager regionManager;
        IEventAggregator eventAggregator;
        public MainWindowViewModel(ITimeService timeServiceValue,
            IContainerProvider containerProviderValue,
            IEventAggregator eventAggregatorValue)
        {
            timeService= timeServiceValue;
            containerProvider= containerProviderValue;
            eventAggregator = eventAggregatorValue;
            eventAggregator.GetEvent<MsgPayLoadEvent>().Subscribe(OnStatusMsgEventReceived);
            regionManager = containerProvider.Resolve<IRegionManager>();
            TimeStr = timeService.GetTimeNow();
            MainStatus = "Ready...";
            NavigateCommand = new DelegateCommand<string>(NavigateCommandExecuted);
            Task.Run(() =>
            {
                InitTimer();
            });
        }

        private void OnStatusMsgEventReceived(MsgPayLoad load)
        {
            MainStatus = $"{load.Idx},{load.TimeStr},{load.Msg}";
        }

        private void NavigateCommandExecuted(string viewName)
        {
            regionManager.RequestNavigate("MainRegion", viewName);
        }

        private void InitTimer()
        {
            System.Timers.Timer tmr=new System.Timers.Timer();
            tmr.Elapsed += Tmr_Elapsed;
            tmr.Interval = 1000;
            tmr.Start();
        }

        private void Tmr_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
        {
            TimeStr = timeService.GetTimeNow();
        }

        public DelegateCommand<string> NavigateCommand { get; set;  }

        private string timeStr;
        public string TimeStr
        {
            get
            {
                return timeStr; 
            }
            set
            {
                SetProperty(ref timeStr, value);
            }
        }


        private string mainStatus;
        public string MainStatus
        {
            get
            {
                return mainStatus; 
            }
            set
            {
                SetProperty(ref mainStatus, value);
            }
        }
    }
}

<prism:PrismApplication x:Class="WpfApp29.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApp29"
             xmlns:prism="http://prismlibrary.com/"> 
</prism:PrismApplication>


using BookProject;
using ImageProject;
using System.Configuration;
using System.Data;
using System.Windows;
using WpfApp29.Service;
using WpfApp29.ViewModels;

namespace WpfApp29
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : PrismApplication
    {
        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }

        protected override void OnInitialized()
        {
            base.OnInitialized();
            var regionManager = Container.Resolve<IRegionManager>();
            regionManager.RequestNavigate("MainRegion", "BookView");
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.Register<ITimeService, TimeService>();
            containerRegistry.RegisterForNavigation<MainWindow, MainWindowViewModel>();
        }

        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
        {
            base.ConfigureModuleCatalog(moduleCatalog);
            moduleCatalog.AddModule<BookModule>();
            moduleCatalog.AddModule<ImageModule>();
        }
    }

}
<Window x:Class="WpfApp29.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:WpfApp29"
        xmlns:prism="http://prismlibrary.com/"
        WindowState="Maximized"
        VerticalAlignment="Stretch"
        HorizontalAlignment="Stretch"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding TimeStr}" FontSize="30" Grid.Column="0"/>
            <Button Content="DgView" Command="{Binding NavigateCommand}" CommandParameter="BookView" Grid.Column="1"/>
            <Button Content="ImageView" Command="{Binding NavigateCommand}" CommandParameter="ImageView" Grid.Column="2"/>
        </Grid>

        <ContentControl Grid.Row="1" prism:RegionManager.RegionName="MainRegion"
                        VerticalAlignment="Stretch"
                        HorizontalAlignment="Stretch"/>

        <TextBlock Grid.Row="2" Text="{Binding MainStatus}" FontSize="30"/>
    </Grid>
</Window>

 

posted @ 2025-10-08 17:02  FredGrit  阅读(8)  评论(0)    收藏  举报