0

Помогите разобраться как правильно реализовать 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;
    }
/// &lt;summary&gt;
/// Команда. Показать окно &quot;Все отделы&quot;
/// &lt;/summary&gt;
//для создания команды используем 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-контейнерами, скиньте пожалуйста.

Спасибо!

aepot
  • 49,560
Andrey
  • 59
  • 6
  • 2
  • 1
    Ну технически вы верно делаете. А вопрос сопоставления вьюмодели окну - тут что удобнее для вас. Можно по именам отбрасывая ViewModel и заменяя на View, можно аттрибутами пометить, можно явно сопоставить. Тут MVVM уже не причем. – vitidev Aug 24 '22 at 17:43
  • Всем большое спасибо! – Andrey Aug 27 '22 at 18:49

0 Answers0