找回密码
 立即注册
查看: 357|回复: 0

WPF Prism的ViewModelLoctor对象个性化匹配、IOC、事件聚合器

[复制链接]
发表于 2022-3-7 15:33 | 显示全部楼层 |阅读模式
Prism的ViewModelLoctor对象个性化匹配、IOC、事件聚合器

<hr>
    更改命名约定

      更改命名约定

    设计思路:

      利用视图的类型全名称,将其中Views替换成ViewModels

      检查类型是不是以View结尾

    • 最终返回一个ViewModel的类型

      新建文件夹/窗口【ViewTest/MainWindow.xaml】,代码如下:
      <Window x:Class="WpfApp6.ViewTest.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:WpfApp6.ViewTest"       xmlns:prism="http://prismlibrary.com/"        prism:ViewModelLocator.AutoWireViewModel="true"        mc:Ignorable="d"        Title="MainWindow" Height="450" Width="800">    <Grid>        <StackPanel>            <TextBlock Text="您好"></TextBlock>            <TextBlock Text="{Binding Value}"></TextBlock>        </StackPanel>    </Grid></Window> 新建文件夹/类【ViewModelTest/MainViewModel】,代码如下:using Prism.Mvvm;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace WpfApp6.ViewModelTest{    public  class MainViewModel:BindableBase     {        private string  _value = "Hellow Word";         public string  Value        {            get { return _value; }            set {             SetProperty(ref _value, value);            }        }    }}
      App.xaml.cs 代码新增重写方法:【ConfigureViewModelLocator】   来配置个性化规则
      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.Threading.Tasks;using System.Windows;namespace WpfApp6{    /// <summary>    /// Interaction logic for App.xaml    /// </summary>    public partial class App : PrismApplication    {        protected override Window CreateShell()        {             return  Container.Resolve<ViewTest.MainWindow>();           }        protected override void RegisterTypes(IContainerRegistry containerRegistry)        {                     }        /// <summary>        /// 配置ViewModelLocator的匹配规则         /// </summary>        protected override void ConfigureViewModelLocator()        {             ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((t) => {                //参数  t:需要匹配的视图                //返回需要匹配的ViewModel的类型                 var viewName = t.FullName;                var vmName = viewName.Replace(".ViewTest.", ".ViewModelTest.");                if (vmName.EndsWith("Window"))                    vmName = vmName.Substring(0, vmName.Length - 6);                if (vmName.EndsWith("View"))                    vmName += "Model";                else                    vmName += "ViewModel";                return Type.GetType(vmName);            });        }     }}
    独立注册--4种方式


    场景:
      三不搭情况下:

      可能不在一个程序集

      对象不在指定的目录

      名称不匹配

      解决方案为:独立注册,有四种方式


      • 临时注册某一个关系对象

        新建文件夹:【ViewTest/DemoWin.xaml】,实例代码如下:
        <Window x:Class="WpfApp6.ViewTest.DemoWin"        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"        xmlns:local="clr-namespace:WpfApp6.ViewTest"        mc:Ignorable="d"        Title="DemoWin" Height="450" Width="800">    <Grid>        <TextBlock Text="{Binding Value}"></TextBlock>    </Grid></Window>
        新建文件夹:【ViewModelTest/DemoViewModel.cs】,代码如下:
        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.Threading.Tasks;using System.Windows;namespace WpfApp6{    /// <summary>    /// Interaction logic for App.xaml    /// </summary>    public partial class App : PrismApplication    {        protected override Window CreateShell()        {             return  Container.Resolve<ViewTest.DemoWin>();           }        protected override void RegisterTypes(IContainerRegistry containerRegistry)        {                     }        /// <summary>        /// 配置ViewModelLocator的匹配规则         /// </summary>        protected override void ConfigureViewModelLocator()        {             //临时注册某一个关系对象            //1 类型对接类型   ViewModelLocationProvider.Register(typeof(ViewTest.DemoWin).ToString(),typeof(ViewModelTest.DemoViewModel));        }     }}

      • 类型 对接 工厂
          protected override void ConfigureViewModelLocator()        {             //2 类型 对接 工厂            ViewModelLocationProvider.Register(typeof(ViewTest.DemoWin).ToString(),()=>            {             return Container.Resolve<ViewModelTest.DemoViewModel>();            });        }
        通用工厂
      protected override void ConfigureViewModelLocator()     {       //3  通用工厂       ViewModelLocationProvider.Register<ViewTest.DemoWin>(() => {                return Container.Resolve<ViewModelTest.DemoViewModel>();            });    }


      • 泛型类型
        /// <summary>        /// 配置ViewModelLocator的匹配规则         /// </summary>        protected override void ConfigureViewModelLocator()        {             //4  泛型类型            ViewModelLocationProvider.Register<ViewTest.DemoWin,ViewModelTest.DemoViewModel>();        }



  • IOC思想的应用与业务逻辑


    Prism.Unity框架中自带了类对象注册的方法,在App.xaml.cs中的  RegisterTypes 方法,实例代码如下:
             /// <summary>        /// IOC容器对象的注册        /// </summary>        /// <param name="containerRegistry"></param>        protected override void RegisterTypes(IContainerRegistry containerRegistry)        {            containerRegistry.Register<IDataAccess, DataAccess>();        }
    新建接口类与实现类,代码如下:
    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace WpfApp6.DAL{    public class DataAccess : IDataAccess    {               public string GetData()        {            return "世界和平!";        }    }}using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace WpfApp6.DAL{  public  interface IDataAccess    {        string GetData();    }}
    DemoViewModel代码如下:
    using Prism.Mvvm;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using WpfApp6.DAL;namespace WpfApp6.ViewModelTest{    public class DemoViewModel : BindableBase    {           private string _value="世界和平!";        public string Value        {            get { return _value; }            set            {                SetProperty(ref _value, value);            }        }        //  构造函数注入       // public DemoViewModel(IDataAccess _data)      //  {        //  this.Value =  _data.GetData();      //  }      //属性注入      [Dependency]      private IDataAccess _data{get;set;}    }}事件聚合器 【发布  订阅】


      条件:
      1、注入一个IEvevtAggragator

      2、新建一个事件类并处理消息


    • 代码实现如下

      MainWindowViewModel类
      using Prism.Commands;using Prism.Events;using Prism.Mvvm;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Input;using WpfApp7.Dal;using WpfApp7.Events;namespace WpfApp7.ViewModels{    public class MainWindowViewModel : BindableBase    {        private string _value = "世界和平!";        private readonly IEventAggregator eventAgs;        public string Value        {            get { return _value; }            set            {                SetProperty(ref _value, value);            }        }         public MainWindowViewModel(IDataAccess da, IEventAggregator _eventAgs)        {            //订阅一个事件            eventAgs = _eventAgs;            eventAgs.GetEvent<MessageEvent>().Subscribe((o) => {                this.Value = o.ToString();            });        }        /// <summary>        /// 生产者  发布事件        /// </summary>        public ICommand Btn_Send        {            get => new DelegateCommand<object>((p) =>            {                eventAgs.GetEvent<MessageEvent>().Publish(p);            });        }    }}//备注:    //Subscribe  参数      //第一个参数为:订阅者的执行Action      //第二个参数为:ThreadOption  订阅者使用哪个线程来处理事件。                   //是个枚举                    //.PublisherThread  发布者的执行线程   默认                   //.BackgroundThread  不管在哪个线程发布  这里的Action都在后台线程处理                   //.UIThread   不管在哪个线程发布 这里的Action都在UI线程处理      //第三个参数 是个bool类型  是个开关  默认为 false       //第四个参数  Predicate<TPayload> filter  过滤器  
      新建事件类:Events/MessageEvent  并继承  PubSubEvent<object>  object是为传递的参数
      using Prism.Events;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace WpfApp7.Events{    /// <summary>    /// 定义一个事件类    /// </summary>    public class MessageEvent:PubSubEvent<object>    {    }}
      MainWindow.xaml 代码如下:
      <Window x:Class="WpfApp7.Views.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:WpfApp7.Views"        xmlns:prism="http://prismlibrary.com/"        prism:ViewModelLocator.AutoWireViewModel="True"        mc:Ignorable="d"        Title="MainWindow" Height="450" Width="800">    <Grid>        <StackPanel>             <Button Content="生产者" Command="{Binding Btn_Send}" CommandParameter="123"></Button>            <TextBlock Text="{Binding Value}" ></TextBlock>        </StackPanel>    </Grid></Window>

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 17:23 , Processed in 0.089306 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表