Перейти к основному содержимому

Практикум WPF — клиент на Prism

Разработчику Архитектору

Практикум, шаг 4 из 6. Собираем TaskDesk.Client с Prism — DI, регионы и навигация поверх MVVM. ViewModel из шага 2; API из шага 3.


Зачем Prism поверх "голого" WPF

Prism (Prism Library, открытый проект на GitHub) добавляет к MVVM:

ВозможностьБез PrismС Prism
DI контейнерРучной new в App.xaml.csRegisterTypes, внедрение в VM
НавигацияСмена Content вручнуюIRegionManager, URI TaskListView
МодульностьОдин exeIModule, lazy-load (в крупных системах)
События между VMСвязанные ссылкиIEventAggregator

Для TaskDesk достаточно Prism.DryIoc (контейнер DryIoc в комплекте) и одного модуля с двумя View.


Пакеты и шаблон проекта

cd TaskDesk/src
dotnet new wpf -n TaskDesk.Client -o TaskDesk.Client
dotnet add TaskDesk.Client reference ../TaskDesk.Core
dotnet add TaskDesk.Client package Prism.DryIoc
dotnet add TaskDesk.Client package CommunityToolkit.Mvvm
dotnet add TaskDesk.Client package Microsoft.Extensions.Configuration.Json

Структура папок:

TaskDesk.Client/
├── App.xaml / App.xaml.cs → PrismApplication
├── Views/
│ ├── ShellWindow.xaml → оболочка с регионом
│ └── TaskListView.xaml
├── ViewModels/
│ ├── ShellViewModel.cs
│ └── TaskListViewModel.cs
├── Services/
│ └── ApiTaskRepository.cs
└── appsettings.json → BaseUrl API

PrismApplication — точка входа

App.xaml:

<prism:PrismApplication x:Class="TaskDesk.Client.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/">
<Application.Resources>
<!-- общие стили -->
</Application.Resources>
</prism:PrismApplication>

App.xaml.cs:

Код ITЗагрузка примера кода…


Shell — окно с регионом

ShellWindow.xaml:

Код ITЗагрузка примера кода…

Prism подставляет в ContentControl View, зарегистрированную через RegisterForNavigation. DataContext ViewModel создаётся автоматически и получает зависимости из DI.


ApiTaskRepository — HttpClient к API

appsettings.json:

{
"TaskDeskApi": {
"BaseUrl": "http://localhost:5100/"
}
}

Код ITЗагрузка примера кода…

Регистрация HTTP в RegisterTypes (упрощённый вариант для учебного проекта):

container.RegisterSingleton<ITaskRepository>(c =>
{
var config = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: true)
.Build();
var baseUrl = config["TaskDeskApi:BaseUrl"] ?? "http://localhost:5100/";
var http = new HttpClient { BaseAddress = new Uri(baseUrl) };
return new ApiTaskRepository(http);
});

Конструктор ApiTaskRepository в этом случае принимает HttpClient напрямую. В production-проекте предпочтительнее IHttpClientFactory через Microsoft.Extensions.Http и named client — см. DI в .NET.


ViewModel с загрузкой при навигации

Prism поддерживает IInitializable / INavigationAware:

Код ITЗагрузка примера кода…

При каждом входе на экран список подтягивается с сервера.


Обработка ошибок сети

Код ITЗагрузка примера кода…

В View — TextBlock с красным текстом, привязанный к ErrorMessage.


EventAggregator — опционально

Если позже появится второй View ("Детали задачи"), можно оповестить список без жёсткой связи:

public class TaskChangedEvent : PubSubEvent { }

// после сохранения
_eventAggregator.GetEvent<TaskChangedEvent>().Publish();

// в TaskListViewModel — подписка в ctor, отписка в Destroy

Для минимального TaskDesk достаточно повторного LoadTasks после Create.


Запуск связки

Терминал 1:

dotnet run --project src/TaskDesk.Api --urls http://localhost:5100

Терминал 2:

dotnet run --project src/TaskDesk.Client

Чек-лист шага 4

  • PrismApplication создаёт ShellWindow и регистрирует навигацию.
  • TaskListViewModel получает ITaskRepository через конструктор.
  • ApiTaskRepository читает BaseUrl из конфигурации.
  • Ошибка сети отображается в UI, приложение не падает.

Дальше: Тестирование.


См. также