【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;
    }
}
相关推荐
死也不注释2 小时前
【鸡零狗碎记录】
unity·c#
Maybe_ch2 小时前
.NET-键控服务依赖注入
开发语言·c#·.net
永卿0014 小时前
设计模式-迭代器模式
java·设计模式·迭代器模式
使二颗心免于哀伤4 小时前
《设计模式之禅》笔记摘录 - 10.装饰模式
笔记·设计模式
★YUI★5 小时前
学习游戏制作记录(剑投掷技能)7.26
学习·游戏·unity·c#
小乖兽技术6 小时前
C#与C++交互开发系列(二十四):WinForms 应用中嵌入C++ 原生窗体
c++·c#·交互
界面开发小八哥7 小时前
界面组件DevExpress WPF中文教程:Grid - 如何过滤节点?
.net·wpf·界面控件·devexpress·ui开发
I'mSQL7 小时前
C#与WPF使用mvvm简单案例点击按钮触发弹窗
开发语言·c#·wpf
工藤新一OL7 小时前
把xml的格式从utf-8-bom转为utf-8
xml·c#·asp.net·.netcore·visual studio
Amagi.8 小时前
Java设计模式-建造者模式
java·设计模式·建造者模式