全稱:Inversion of Control,控制反轉
場景:A頁面需要調用B/C頁面等,防止直接在VM中新建別的頁面實例,使用IOC設計架構;
創建Service,在Service中實現頁面的實例創建和定義頁面輸入輸出參數。
在MainView中注冊A、B、C頁面的Service。
A需要調用B時,調用B的Service。
此架構思路可以在MVVM基礎上,減少不同模塊的耦合。
可以所有模塊的頁面都注冊服務。讓VM之間不存在互相調用
手動實現
IOC類
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接口
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接口
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實現
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;}
}