xiangtingsl 发表于 2022-3-7 15:33

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

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{    publicclass MainViewModel:BindableBase   {      private string_value = "Hellow Word";         public stringValue      {            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()      {             returnContainer.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()      {             returnContainer.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{publicinterface 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();      //}      //属性注入            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>

页: [1]
查看完整版本: WPF Prism的ViewModelLoctor对象个性化匹配、IOC、事件聚合器