I was facing an issue where I want to retrieve existing/active ViewModels from the Prism runtime.
Here’s the code I’ve done to achieve it:
public class ViewModelFinder { readonly IRegionManager _RegionManager; readonly IContainer _Container; public ViewModelFinder(IContainer container, IRegionManager regionManager) { _RegionManager = regionManager; _Container = container; } public TViewModel FindOrResolve<TViewModel>() where TViewModel : class => Find<TViewModel>() ?? _Container.Resolve<TViewModel>(); /// <summary> /// Locates an existing VM in the entire region manager. /// </summary> public TViewModel Find<TViewModel>() => (TViewModel)Find(typeof(TViewModel)); public object Find(Type viewModelType) { var shellContext = Application.Current.MainWindow.DataContext; if (shellContext != null && viewModelType.IsAssignableFrom(shellContext.GetType())) return shellContext; foreach (var region in _RegionManager.Regions) { var viewModel = Find(region, viewModelType); if (viewModel != null) return viewModel; } return null; } /// <summary> /// Locates an existing VM in the specified region. /// </summary> public TViewModel Find<TViewModel>(IRegion region) => (TViewModel)Find(region, typeof(TViewModel)); public object Find(IRegion region, Type viewModelType) { foreach (var view in region.Views.OfType<FrameworkElement>()) if (view.DataContext != null && viewModelType.IsAssignableFrom(view.DataContext.GetType())) return view.DataContext; return null; } }
It’s intended to be used from any VM, by adding a ViewModelFinder
to its constructor to be resolved by the IoC (in my case DryIoc).
When requesting for a VM, it will check for the Shell, then iterate over all views in all regions until it finds the desired VM.
Would love to hear about any better ways to achieve this.