【WPF】IOC控制反转的应用:弹窗但不互相调用ViewModel

全称:Inversion of Control,控制反转

场景:A页面需要调用B/C页面等,防止直接在VM中新建别的页面实例,使用IOC设计架构;

创建Service,在Service中实现页面的实例创建和定义页面输入输出参数。

在MainView中注册A、B、C页面的Service。

A需要调用B时,调用B的Service。

此架构思路可以在MVVM基础上,减少不同模块的耦合。

可以所有模块的页面都注册服务。让VM之间不存在互相调用

手动实现

IOC类

csharp 复制代码
public static class IoC
{
	private static readonly Dictionary<Type, object> MAP;

	static IoC()
	{
		MAP = new Dictionary<Type, object>();
	}

	public static void Register<T>(T instance)
	{
		MAP[typeof(T)] = instance;
	}

	public static T Provide<T>()
	{
		if (MAP.TryGetValue(typeof(T), out object obj) && obj is T t)
		{
			return t;
		}

		throw new Exception("No registered service of type " + typeof(T));
	}
}

IView接口

csharp 复制代码
public interface IView
{
    /// <summary>
    /// Close the view with the given result
    /// </summary>
    void CloseDialog(bool result);
}

页面B实现IView

复制代码
public partial class ChildValuePopup : Window, IView
{
    public ChildValueEditPopupViewModel ViewModel => (ChildValueEditPopupViewModel)this.DataContext;

    public ChildValuePopup()
    {
        InitializeComponent();
        DataContext = new ChildValueEditPopupViewModel(this);
    }

    public void CloseDialog(bool result)
    {
        this.DialogResult = result;
        this.Close();
    }
}

IViewBService页面B的Service接口

csharp 复制代码
public interface IChildValueEditPopupService
{
//打开B页面方法,及其输入输出参数
    Task<ChildValueEditPopupResult> ChildValueEditPopupOpenAsync(GirdDataModel data);

    ChildValueEditPopupResult ChildValueEditPopupOpen(GirdDataModel data);
}

//输出参数类定义
//IsSuccess是否成功打开B页面
public class ChildValueEditPopupResult : ObservableObject
{
    public bool IsSuccess { get; set; }

    private object _setValue;

    public string code { get; set; }

    public object setValue { get=>_setValue; set=>OnPropertyChanged(ref _setValue,value); }
}

ViewBService页面B的Service实现

csharp 复制代码
internal class ChildValueEditPopupService : IChildValueEditPopupService
{
	public ChildValueEditPopupResult ChildValueEditPopupOpen(GirdDataModel data)
	{
		var popup = new ChildValuePopup();
		popup.ViewModel.Code = data.code;
		popup.ViewModel.ChildValues = Copy.DeepCopy( data.childValues);
		popup.ViewModel.SetValue = data.setValue;

		bool result = popup.ShowDialog() == true;
		if (!result) {
			return new ChildValueEditPopupResult() { IsSuccess = false};
		}

		return new ChildValueEditPopupResult()
		{
			IsSuccess = true,
			code = popup.ViewModel.Code,
			setValue = popup.ViewModel.SetValue,
		}; 
	}

	public async Task<ChildValueEditPopupResult> ChildValueEditPopupOpenAsync(GirdDataModel data) {
		return await Application.Current.Dispatcher.InvokeAsync(() => {
			return ChildValueEditPopupOpen(data);
		});
	}
}

注册服务,全局页面MainView

复制代码
public MainWindow()
{
    InitializeComponent();
    IoC.Register<IChildValueEditPopupService>(new ChildValueEditPopupService());
}

使用服务,页面A打开页面B

复制代码
private void ChildValueEditPopupOpen(GirdDataModel data) {
    IChildValueEditPopupService service = IoC.Provide<IChildValueEditPopupService>();
    ChildValueEditPopupResult res = service.ChildValueEditPopupOpen(data);
    if (res.IsSuccess) {
        data.setValue = res.setValue;
    }
}
相关推荐
唐青枫12 小时前
别只会看日志:C#.NET SOS 调试扩展从 Dump 到内存泄漏排查
c#·.net
yswenli19 小时前
基于C#开发网站视频嗅探下载工具——BrowserVideoGrabber
c#·videodownload·webvideodownload·videograbber
Lost of 程序猿19 小时前
M2 实战:询价与采购订单聚合落地——跨聚合一致性、领域事件与 Outbox
开发语言·c#·asp.net·.net
Polevne21 小时前
C# GRPC 一元与双向流
linux·算法·c#
clz131452121 小时前
如何设计一个优雅可靠的金融级联机接口
wpf
YHL2 天前
🎯 JavaScript 单例模式(Singleton Pattern)—— 从理论到实战
javascript·设计模式
闲云自留地2 天前
云平台存储管理员:Cinder 创建挂载卷 + Swift 分布式存储原理
分布式·wpf·swift
2401_868534782 天前
网络环境规划核心考点全梳理
网络·设计模式
XiaoZhenHua982 天前
C#工业机器视觉Recipe配方系统设计:多型号、多相机、多工位参数如何统一管理
c#·软件架构·机器视觉·工业自动化·工业软件·recipe
fujisheng6612 天前
FUI 导航实践:拆开 Layer、History、Coverage 与 Cache 的组合语义
c#·unity3d