3. Prism

github.com/PrismLibrar…

Prism是一个用于在 WPF Xamarin Form Uno 平台 WinUI 中构建松散耦合、可维护和可测试的 XAML 应用程序框架。

Sample-Demo:學習各部分功能的代碼

github.com/PrismLibrar…

3.1 Install

1.安裝擴展

點擊菜單欄的擴展 -> 搜索Prism -> 重新啟動

2.創建項目

3.我的專案名字FullApp02,設為啟動項。

3.2 NuGet import Prism

1.在NuGet中搜索Prism DryIoc

2.添加名稱空間prism,修改基類

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

一定要記得:刪除StartupUri,不然會出現兩個窗口

3.修改app.xaml.cs,實現PrismApplication

3.3 Detail

1.安裝了prism template插件以後,直接使用prism創建項目

2.查看項目結構,在app.xaml中創建prism的名稱空間,以及修改基類

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

3.app.xaml.cs中實現PrismApplication,重寫裡面的接口

    public partial class App
        protected override Window CreateShell()
            return Container.Resolve<MainWindow>();
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
            containerRegistry.RegisterSingleton<IMessageService, MessageService>();
        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
            moduleCatalog.AddModule<ModuleNameModule>();

4.兩個文件夾的名字ViewsViewModels是固定格式,以及下面的MainWindow.xamlMainWindowViewModel.cs

5.在MainWindows.xaml中帶入prism,以及掃所有的包prism:ViewModelLocator.AutoWireViewModel="True"

<Window x:Class="FullApp01.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/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        xmlns:core="clr-namespace:FullApp01.Core;assembly=FullApp01.Core"
        Title="{Binding Title}" Height="350" Width="525" >
        <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.ContentRegion}" />
    </Grid>
</Window>

3.4 Adapter

<ContentControl prism:RegionManager.RegionName="ContentRegion" />就是在xaml中定義了一個名字的ContentRegion的區域。

上面的代碼能運行,是因為Prism默认提供了几种适配器:
    ContentControlRegionAdapter 内容控制区域适配器
    SelectorRegionAdaptor 选择区域适配器
    ItemsControlRegionAdapter 区域适配器

如果在MainWindow.xaml中不使用ContentControl,而是StackPanel,那麼就無法定義區域,所有只能換條路,自定義一個適配器。

using Prism.Regions;
using System.Windows;
using System.Windows.Controls;
namespace Regions
    public class StackPanelRegionAdapter : RegionAdapterBase<StackPanel>
        public StackPanelRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
            : base(regionBehaviorFactory)
        protected override void Adapt(IRegion region, StackPanel regionTarget)
            region.Views.CollectionChanged += (s, e) =>
                if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
                    foreach (FrameworkElement element in e.NewItems)
                        regionTarget.Children.Add(element);
                //handle remove
        protected override IRegion CreateRegion()
            return new AllActiveRegion();

最後在app.xaml.cs内注册StackPanelRegionAdapter,即可完成自定义区域适配器

   protected override void ConfigureRegionAdapterMappings(RegionAdapterMappings regionAdapterMappings)
            base.ConfigureRegionAdapterMappings(regionAdapterMappings);
            regionAdapterMappings.RegisterMapping(typeof(StackPanel),Container.Resolve<StackPanelRegionAdapter>() );

3.5 Module

此部分僅支持.Net Core(不支持.net Framework),使代碼盡最大化的解耦,每個部分都是一個module。

Reference: github.com/PrismLibrar…

1.生成事件 使用其他Model時,需要生成 類庫右鍵 -> 點擊屬性 -> 生成事件

2.視圖注入

[Module(ModuleName = "Contact")]
public class ModuleA : IModule
    public void OnInitialized(IContainerProvider containerProvider)
        //通过注册RegionManager,添加ContactView
        var regionManager = containerProvider.Resolve<IRegionManager>();
        //通过ContentRegion管理导航默认初始页面ViewA
        var contentRegion = regionManager.Regions["ContentRegion"];
        contentRegion.RequestNavigate(nameof(ViewA));
    public void RegisterTypes(IContainerRegistry containerRegistry)
        containerRegistry.RegisterForNavigation<ViewA>();

3.6 Mvvm

1.設置自動關聯

prism:ViewModelLocator.AutoWireViewModel="True"

2.Code

Reference: github.com/PrismLibrar…

namespace UsingDelegateCommands.ViewModels
    public class MainWindowViewModel : BindableBase
        private bool _isEnabled;
        public bool IsEnabled
            get { return _isEnabled; }
                SetProperty(ref _isEnabled, value);
                ExecuteDelegateCommand.RaiseCanExecuteChanged();
        private string _updateText;
        public string UpdateText
            get { return _updateText; }
            set { SetProperty(ref _updateText, value); }
        public DelegateCommand ExecuteDelegateCommand { get; private set; }
        public DelegateCommand<string> ExecuteGenericDelegateCommand { get; private set; }
        public DelegateCommand DelegateCommandObservesProperty { get; private set; }
        public DelegateCommand DelegateCommandObservesCanExecute { get; private set; }
        public MainWindowViewModel()
            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);
        private void Execute()
            UpdateText = $"Updated: {DateTime.Now}";
        private void ExecuteGeneric(string parameter)
            UpdateText = parameter;
        private bool CanExecute()
            return IsEnabled;

3.發佈訂閱和過濾

Reference: github.com/PrismLibrar…

3.7 Router

Reference:github.com/PrismLibrar…

1.目錄結構

  • 點擊按鈕A,顯示ViewA
  • 點擊按鈕B,顯示ViewB

    2.App.xaml注入視圖

    namespace FullApp01
        /// <summary>
        /// Interaction logic for App.xaml
        /// </summary>
        public partial class App
            protected override Window CreateShell()
                return Container.Resolve<MainWindow>();
            protected override void RegisterTypes(IContainerRegistry containerRegistry)
                containerRegistry.RegisterForNavigation<ViewA>();
                containerRegistry.RegisterForNavigation<ViewB>();
            protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
    

    3.MainWindow.xaml自動導入和按鈕點擊傳參

    xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True"

    <Window
    
    
    
    
        
     x:Class="FullApp01.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/"
            prism:ViewModelLocator.AutoWireViewModel="True"
            xmlns:core="clr-namespace:FullApp01.Core;assembly=FullApp01.Core"
            Title="{Binding Title}" Height="550" Width="850" >
        <Window.Resources>
            <Style TargetType="Button" x:Key="left_btn">
                <Setter Property="Height" Value="45"/>
                <Setter Property="Width" Value="80"/>
                <Setter Property="Background" Value="GreenYellow"/>
                <Setter Property="Margin" Value="5"/>
            </Style>
        </Window.Resources>
            <Grid.RowDefinitions>
                <RowDefinition Height="100"/>
                <RowDefinition />
            </Grid.RowDefinitions>
            <Border Grid.Row="0">
                <TextBlock Height="60" Width="650" Background="AliceBlue" Text="Prism Template"/>
            </Border>
            <Grid Grid.Row="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="150"/>
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <Border Grid.Column="0" Background="Orchid">
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition />
                            <RowDefinition />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Button Grid.Row="0" Content="Btn01" Style="{StaticResource left_btn}" Command="{Binding NavigateCommand}" CommandParameter="ViewA"></Button>
                        <Button Grid.Row="1" Content="Btn02" Style="{StaticResource left_btn}" Command="{Binding NavigateCommand}" CommandParameter="ViewB"></Button>
                        <Button Grid.Row="2" Content="Btn03" Style="{StaticResource left_btn}"></Button>
                        <Button Grid.Row="3" Content="Btn04" Style="{StaticResource left_btn}"></Button>
                    </Grid>
                </Border>
                <Border Grid.Column="1" Margin="2">
                    <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.ContentRegion}" />
                </Border>
            </Grid>
        </Grid>
    </Window>
    

    4.MainVindowViewModel處理方法

    namespace FullApp01.ViewModels
        public class MainWindowViewModel : BindableBase
            private string _title = "Prism Application";
            private readonly IRegionManager _regionManager;
            public string Title
                get { return _title; }
                set { SetProperty(ref _title, value); }
            public DelegateCommand<string> NavigateCommand { get; private set; }
            public MainWindowViewModel(IRegionManager regionManager)
                _regionManager = regionManager;
                NavigateCommand = new DelegateCommand<string>(Navigate);
            private void Navigate(string navigatePath) 
                if (NavigateCommand != null) 
                    _regionManager.RequestNavigate("ContentRegion", navigatePath);
            chenhongdong
            Vue.js
            JavaScript
                            
  • 私信