【WPF嵌套vue3】4. .netcore 6.0 WPF 使用prism

WPF框架简介

虽然WPF只是作为一个盒子/容器使用,但是WPF我还是用上了Prism框架,来实现WPF项目的MVVM架构思想
初次使用Prism,需要有一定的WPF开发经验,话不多说,开始吧

App.xaml的修改

  • wpf的程序入口是从app.xaml开始的,开始对其进行修改
    prism根节点代替原来的app节点,同时增加xmls:prism节点xmls:hc
    • xml:hc是HandyControl前端UI控件,不用可以不用添加
    • xmls:prism 是关键的Prism节点
    • 去除了 StartUri 默认启动页面,改为在App.xaml.cs启动页面
<prism:PrismApplication x:Class="WPF.NetCore.Startup.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WPF.NetCore.Startup"
                         xmlns:prism="http://prismlibrary.com/"
             xmlns:hc="https://handyorg.github.io/handycontrol" >
    <Application.Resources>
    </Application.Resources>
</prism:PrismApplication>

App.xaml.cs的修改

主要修改了几个地方

  • 修改app.xaml.cs集成的Application 变成了 PrismApplication
  • 去继承实现 CreateShell(),注册TextEncoding(好像是解决中文乱码的问题…记不清了)
  • 打开首界面,首界面为 MainWindow
  • RegisterTypes() 注册Prism页面,我用了反射去写,到时候大家可以去看源码 (如果只是简单的几个页面,也可以直接手工注册)
  • ConfigureViewModelLocator() 修改Prism viewmodel文件的映射名,比如 wpf.netcore.startup.xaml,修改后就prism框架就会去寻找wpf.netcore.startupVM.xaml
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Unity;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;

namespace WPF.NetCore.Startup
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : PrismApplication
    {
    	//初始化创建
        protected override Window CreateShell()
        {
            System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
            return Container.Resolve<WPF.NetCore.Startup.MainWindow>(); 
        }
        #region 重写Prism框架部分方法
        #region 重写ViewModel的命名方法
        /// <summary>
        /// 重写ViewModel的命名方法,修改默认名称为 xxxVM.cs
        /// </summary>
        protected override void ConfigureViewModelLocator()
        {
            base.ConfigureViewModelLocator();
            ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
            {
                var viewName = viewType.FullName.Replace(".ViewModels.", ".CustomNamespace.");
                var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
                var viewModelName = $"{viewName}VM, {viewAssemblyName}";
                return Type.GetType(viewModelName);
            });
        }
        #endregion
        /// <summary>
        /// prism页面注册
        /// </summary>
        /// <param name="containerRegistry"></param>
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            //页面注册
            WPF.NetCore.PrismCore.RegisterTools.RegisterPrismInit(containerRegistry);
        }
        #endregion

    }
}

首界面代码修改 MainWindow

首界面中修改了如下(都是prism框架的基本规则):

  • 增加xmlns:prism=“http://prismlibrary.com/”(prism框架引用)
  • prism:ViewModelLocator.AutoWireViewModel=“True”(使用vm文件)
  • xmlns:b=“http://schemas.microsoft.com/xaml/behaviors”(事件触发)
  • 增加了对应的Loaded(初始化加载事件)
  • 在内容中,增加了ContentControl这个组件,用于放置Prism的内容容器
<Window x:Class="WPF.NetCore.Startup.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:WPF.NetCore.Startup.Control"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
         xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
          xmlns:b="http://schemas.microsoft.com/xaml/behaviors" 
        >
    <b:Interaction.Triggers>
        <b:EventTrigger EventName="Loaded">
            <b:InvokeCommandAction Command="{Binding Loaded}" />
        </b:EventTrigger>
    </b:Interaction.Triggers>
    <Grid>
        <ContentControl prism:RegionManager.RegionName="FrameView" x:Name="FrameView" />
    </Grid>
</Window>

对应的cs文件

添加了Region容器注册,不知道朋友可以去看下相关的

using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
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;
using WPF.NetCore.Public.PublicConst;

namespace WPF.NetCore.Startup
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            RegionManager.SetRegionName(this.FrameView, RegionConst.FrameView);
        }
    }
}

MainWindowVM文件

添加了load方法,并实现,跳转了一个页面 MainBrowser(UserControl类型)

using Prism.Commands;
using Prism.Ioc;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using WPF.NetCore.PrismCore.Model;
using WPF.NetCore.Public.PublicConst;
using WPF.NetCore.Startup.Control;

namespace WPF.NetCore.Startup
{
    public class MainWindowVM : BasicVM
    {
        public MainWindowVM(IContainerExtension container) : base(container)
        {

        }

        public DelegateCommand Loaded => new DelegateCommand(async () => await Load());

        /// <summary>
        /// 页面加载
        /// </summary>
        /// <returns></returns>
        async Task Load()
        {
            IRegion region = RegionManager.Regions[RegionConst.FrameView];
            region.RequestNavigate("WPF.NetCore.Startup.Control.MainBrowser");
        }
    }
}

PS:注册及反射相关代码

using Prism.Ioc;
using Prism.Modularity;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using WPF.NetCore.Common;

namespace WPF.NetCore.PrismCore
{
    /// <summary>
    /// 注册帮助类
    /// </summary>
    public class RegisterTools
    {
        /// <summary>
        /// 初始化 注册方法
        /// </summary>
        /// <param name="containerRegistry"></param>
        public static void RegisterPrismInit(IContainerRegistry containerRegistry)
        {
            //将所有的UserControl注册到Region中
            //注册所有的Page,windows和control
            RegisterPrism<Page>(containerRegistry);
            RegisterPrism<Window>(containerRegistry);
            RegisterPrism<UserControl>(containerRegistry);
        }

        /// <summary>
        /// 初始化 注册方法
        /// </summary>
        /// <param name="containerRegistry"></param>
        public static void RegisterPrismModule(IModuleCatalog moduleCatalog)
        {
            //注册系统模块
            //RegisterPrism<IModule>(moduleCatalog);
        }
        /// <summary>
        /// 各类型组件注册
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="containerRegistry"></param>
        private static void RegisterPrism<T>(IContainerRegistry containerRegistry)
        {
            var ass = DllTools.FindAssemblies();
            if (ass != null)
            {
                var result = ass.SelectMany(t => t.GetTypes()).Where(i => i.IsSubclassOf(typeof(T)));
                foreach (var type in result)
                {
                    containerRegistry.RegisterForNavigation(type, type.FullName);
                }
            }
        }

        /// <summary>
        /// 各类型组件注册
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="containerRegistry"></param>
        private static void RegisterPrism<T>(IModuleCatalog moduleCatalog)
        {
            var ass = DllTools.FindAssemblies();
            if (ass != null)
            {
                var result = ass.SelectMany(t => t.GetTypes()).Where(i => i.IsSubclassOf(typeof(T)));
                foreach (var type in result)
                {
                    moduleCatalog.AddModule(new ModuleInfo
                    {
                        ModuleName = type.Name,
                        ModuleType = type.AssemblyQualifiedName,
                        InitializationMode = InitializationMode.OnDemand
                    });
                }
            }
        }

        /// <summary>
        /// 为主窗口注册所有的UserControl
        /// </summary>
        /// <param name="regionName"></param>
        public static void RegisterUserControlToRegion(IRegionBehaviorFactory containerRegistry, string regionName)
        {
            var ass = DllTools.FindAssemblies();
            if (ass != null)
            {
                var result = ass.SelectMany(t => t.GetTypes()).Where(i => i.IsSubclassOf(typeof(UserControl)));
                foreach (var type in result)
                {
                    containerRegistry.AddIfMissing(regionName, type);
                }
            }
        }
    }
}

通过反射来取项目里面的所有的dll

using Microsoft.Extensions.DependencyModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace WPF.NetCore.Common
{
    /// <summary>
    /// Dll模块帮助类
    /// </summary>
    public class DllTools
    {
        /// <summary>
        /// 获取本地目录下的所有dll
        /// </summary>
        /// <returns></returns>
        public static List<Assembly> GetAssemblies()
        {
            var referenceAssemblies = new List<Assembly>();
            string[] assemblyNames = DependencyContext.Default.GetDefaultAssemblyNames().Select(p => p.Name).ToArray();
            assemblyNames = GetFilterAssemblies(assemblyNames).Distinct().ToArray();
            foreach (var name in assemblyNames)
            {
                referenceAssemblies.Add(Assembly.Load(name));
            }
            return referenceAssemblies;
        }
        /// <summary>
        /// 获取所有的dll组件
        /// </summary>
        /// <returns></returns>
        public static Assembly[] FindAssemblies()
        {
            string[] filters =
            {
                "mscorlib",
                "netstandard",
                "dotnet",
                "api-ms-win-core",
                "runtime.",
                "System",
                "Microsoft",
                "Window",
            };
            DependencyContext context = DependencyContext.Default;
            if (context != null)
            {
                List<string> names = new List<string>();
                string[] dllNames = context.CompileLibraries.SelectMany(m => m.Assemblies).Distinct().Select(m => m.Replace(".dll", ""))
                    .OrderBy(m => m).ToArray();
                if (dllNames.Length > 0)
                {
                    names = (from name in dllNames
                             let i = name.LastIndexOf('/') + 1
                             select name.Substring(i, name.Length - i)).Distinct()
                        .Where(name => !filters.Any(name.StartsWith))
                        .OrderBy(m => m).ToList();
                }
                else
                {
                    foreach (CompilationLibrary library in context.CompileLibraries)
                    {
                        string name = library.Name;
                        if (name == "KWT") continue;
                        if (!names.Contains(name))
                        {
                            names.Add(name);
                        }
                    }
                }
                return LoadFiles(names);
            }

            //遍历文件夹的方式,用于传统.netfx
            string path = Directory.GetCurrentDirectory();
            string[] files = Directory.GetFiles(path, "*.dll", SearchOption.TopDirectoryOnly)
                .Concat(Directory.GetFiles(path, "*.exe", SearchOption.TopDirectoryOnly))
                .ToArray();

            return files.Where(file => filters.All(token => Path.GetFileName(file)?.StartsWith(token) != true)).Select(Assembly.LoadFrom).ToArray();
        }
        /// <summary>
        /// Dll文件过滤
        /// </summary>
        /// <param name="assemblyNames"></param>
        /// <returns></returns>
        private static string[] GetFilterAssemblies(string[] assemblyNames)
        {
            //var relatedFile = "WPF.Net";
            var pattern = "^Microsoft.\\w*|^System.\\w*|^runtime.\\w*|^Newtonsoft.Json.\\w*";
            Regex notRelatedRegex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
            return
                assemblyNames.Where(
                    name => !notRelatedRegex.IsMatch(name)).ToArray();
        }

        private static Assembly[] LoadFiles(IEnumerable<string> files)
        {
            List<Assembly> assemblies = new List<Assembly>();
            foreach (string file in files)
            {
                AssemblyName name = new AssemblyName(file);
                try
                {
                    assemblies.Add(Assembly.Load(name));
                }
                catch (FileNotFoundException)
                { }
            }
            return assemblies.ToArray();
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值