Помогите разобраться как правильно реализовать MVVM.
Не могу понять как правильно организовать открытие новых окон соответствующих нужным ViewModel-ям с помощью IoC-контейнеров.
Насколько я понимаю в MVVM ViewModel ничего не должна знать о View.
Проект: 1 Главный WPF-проект содержит два Windows:
- MainWindow
- DepartmentsWindow
Здесь же реализован метод ShowWindow выводящий новое окно для ViewModel-и
public partial class App : Application
{
public IServiceProvider Services { get; }
public static App CurrentApp => (App)Application.Current;
public App()
{
Services = ConfigureServices();
var winService= Services.GetService<IWindowsService>();
winService.Services = this.Services;
winService.ShowWindow = ShowWindow;
winService.ShowMessage = ShowMessage;
}
protected override void OnStartup(System.Windows.StartupEventArgs e)
{
base.OnStartup(e);
var mainViewModel = Services.GetService<MainWindowViewModel>(); //создаём ViewModel главного окна
var window = new MainWindow() { DataContext = mainViewModel };
window.Show();
}
//Словарь в котором каждому ViewModel сопоставлен свой View
static Dictionary<Type, Type> windowsTypesList = new Dictionary<Type, Type>();
private static IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
services.AddSingleton<IWindowsService, WindowsService>();
services.AddTransient<MainWindowViewModel>();
services.AddTransient<DepartmentsViewModel>();
services.AddTransient<DepartmentsWindow>();
windowsTypesList[ typeof(DepartmentsViewModel)] = typeof(DepartmentsWindow);
return services.BuildServiceProvider();
}
/// <summary>
/// Показать окно соответствующее ViewModel-и
/// </summary>
/// <param name="vm"></param>
public void ShowWindow(Type vm)
{
var viewModel = Services.GetService(vm);
Type? windowType;
windowsTypesList.TryGetValue(vm, out windowType);
var window = (Window)Services.GetService(windowType);
window.DataContext = viewModel;
window.ShowDialog();
}
public void ShowMessage(string mes)
{
MessageBox.Show(mes);
}
}
2Есть "промежуточный" класс (в отдельной библиотеке WindowsServiceLibrary) с которым работают ViewModel. Класс сделан чтобы ViewModel ничего не знала о View и работала с ним, а не с View.
public interface IWindowsService
{
public IServiceProvider? Services { get; set; }
public Action<Type> ShowWindow { get; set; }
public Action<string> ShowMessage{ get; set; }
}
public class WindowsService:IWindowsService
{
public IServiceProvider? Services { get; set; }
public Action<Type> ShowWindow { get; set; }
public Action<string> ShowMessage { get; set; }
}
3 Содержимое ViewModel (для главного окна программы) Здесь реализована команда!
public partial class MainWindowViewModel
{
IWindowsService service;
public MainWindowViewModel(IWindowsService service)
{
this.service = service;
}
/// <summary>
/// Команда. Показать окно "Все отделы"
/// </summary>
//для создания команды используем NET Community Toolkit 8.0! MVVM
[RelayCommand]
public void ShowAllDepartmentsWindow()
{
service.ShowWindow(typeof(DepartmentsViewModel));
}
}
т.е. в этой команде мы "говорим" <Показать окно для следующей ViewModel - DepartmentsViewModel>
В окне стандартный вызов команды
<Button
Height="20" Width="120"
Command="{Binding ShowAllDepartmentsWindowCommand}">Отделы</Button>
Правильно ли так реализовывать MVVM?
Правильно ли создавать класс типа WindowsService через который выводить новые окна?
Ведь он нужен только чтобы ViewModel ничего не знала о View.
Как правильно реализовать работу команд с помощью IoC?
Если есть пример полноценной реализации MVVM с КОМАНДАМИ и с IoC-контейнерами, скиньте пожалуйста.
Спасибо!