【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;
    }
}
相关推荐
啦啦啦啦啦zzzz5 小时前
设计模式:桥接模式和组合模式
c++·设计模式·组合模式·桥接模式
dalong105 小时前
WPF:3D甜甜圈
3d·c#·wpf·甜甜圈
别催小唐敲代码7 小时前
ROS2从入门到实战:去中心化机器人操作系统详解
wpf·ros2
神秘的MT9 小时前
C# WinForm Socket 类 常用方法 (C# .NET,TCP 场景)
服务器·网络·学习·tcp/ip·c#·winform
神罚天下ET21 小时前
c# ACME client (补充)
开发语言·c#
饼干哥哥1 天前
字节Seedance2.5终于上线,这次在收割谁?
人工智能·设计模式·前端框架
董员外1 天前
RAG 系统进化论(六):GraphRAG(基于知识图谱的 RAG),从相似文本走向实体关系
人工智能·后端·设计模式
噗噗夹的TA之旅1 天前
Shader 学习 21:自定义 Render Feature
学习·游戏·unity·c#·游戏引擎·图形渲染
脚踏实地皮皮晨1 天前
003006001_WrapPanel控件
开发语言·c#·.net·wpf·visual studio
鬼鬼鬼1 天前
从 Prompt 到 Harness:企业级 Agent 工程的完整演进之路
设计模式·架构·ai编程