Sunday, November 22, 2015

Introduction to Prism 6

Здравствуйте, уважаемые читатели. Сегодня мы поговорим о том, как использовать Prism 6 в своих приложениях для WPF. Не так давно меня просили показать, как использовать Prism 6 для Windows 10 UWP приложений. Я уже подготовил материал и постараюсь в ближайшее время опубликовать на эту тему статью. Использование Prism 6 для Windows 10 UWP выглядит для меня как-то более живо, чем то же самое для WPF. В общем, если вам интересна тема разработки под Windows 10 с использованием Prism 6, буду рад раскрыть ее в цикле статей на эту тему. Надеюсь, это будет кому-то интересно, тем более что есть большая вероятность, что новая команда Prism добавит еще что-то интересное к своему детищу. А пока же вернемся к использованию Prism 6 в своих приложениях. Не так давно я описал основные отличия, которые коснулись Prism 6, по сравнению с Prism, 5 в статье "Prism 6: what's on?"сделав подробный отчет по библиотекам и списку изменений, которые коснулись самого Prism 6. Задача же данной статьи – показать, в каком плане упростилась разработка, или она осталась на том же месте. 
Приступим к реализации. Для начала создадим новый WPF проект, который назовем “PrismSixSample”.
Затем поставим все необходимые пакеты. Мне нравится тот факт, что всех их можно установить в один клик. Для этого достаточно указать, какой загрузчик мы будем использовать. Так как я использую в основном Unity, то выбор для меня был очевиден.
После установки пакета Unity for Prism 6” мы увидим, что все необходимые зависимости, указанные в пакете, сразу остановятся.
Перейдем в список установленных программ и убедимся, что у нас все пакеты, требуемые для работы, успешно установились.
Теперь немного теории о том, что это за пакеты, для тех, кто не знает, какие изменения произошли в Prism 6. У нас осталось две библиотеки: Prism.dll и Prism.Wpf.dll. Первая библиотека  это ядро, вторая предоставляет нам интерфейс для работы с XAML (ViewModels, разные хелперы, взаимодействие с окнами, регионами и т.д.). Рекомендую посмотреть мою статью, ссылка на которую я приведена выше. Это не займет много времени, и вы будете знать, что куда переехало. Теперь приступим к разбиению проекта на модели, согласно паттерну MVVM.
Папку Services я добавил по той причине, что мы будем добавлять сервис, который будет нам возвращать информацию по нашей модели. Такая себе эмуляция сервиса, который выбирает информацию с БД. Начнем, пожалуй, с добавления новой модели TestModel в нашу папку Models.
public class TestModel : BindableBase
{
    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged();
        }
    }
}
Эта информация будет просто отображаться в UI в виде списка. Затем приступим к реализации сервиса, который будет возвращать нам информацию по модели. Для этого в нашу папку Services добавим новый интерфейс ITestModelService, который показан в примере ниже.
public interface ITestModelService
{
    void GetItems(Action<List<TestModel>> action);
}
Затем в этой же папке добавим имплементацию этого интерфейса в классе TestModelService.
public class TestModelService : ITestModelService
{
    public void GetItems(Action<List<TestModel>> action)
    {
        var items = new List<TestModel>
        {
            new TestModel { Name = "Alex"},
            new TestModel { Name = "Igor"},
            new TestModel {Name = "Denis"}
        };

        action(items);
    }
}
Как видите, реализация довольно примитивная. Теперь перейдем в нашу папку ViewModels и добавим нашу модель представления, которая будет отвечать за реализацию взаимодействия между представлением и нашей моделью. Назовем нашу модель представления MainWindowViewModel и посмотрим на ее реализацию ниже.
public class MainWindowViewModel : BindableBase
{
    private ITestModelService _modelService;
    public MainWindowViewModel(ITestModelService modelService)
    {
        _modelService = modelService;
        _modelService.GetItems(items =>
        {
            Items = new ObservableCollection<TestModel>(items);
        });
    }

    public ObservableCollection<TestModel> Items { getset; }
}
Следующим делом необходимо перенести наше главное окно в Views папку. Переименовывать мы его не будем, просто поправим пространства имен, чтобы они были корректные. Сразу же удалим с App.xaml поле StartupUri, потому что загрузку нашего представления и настройку начальных параметров мы возложим на наш загрузчик (bootstrapper), который мы реализуем в самом конце.
После того как вы перенесли ваше представление в нужную папку, пришло время его отредактировать. Для примера я просто вывел информацию по созданной тестовой модели в список.
<Window x:Class="PrismSixSample.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox ItemsSource="{Binding Items}">
          <ListBox.ItemTemplate>
            <DataTemplate>
              <StackPanel Orientation="Horizontal">
                <TextBlock Padding="5,0,5,0"
                  Text="{Binding Name}" />
              </StackPanel>
            </DataTemplate>
          </ListBox.ItemTemplate>
        </ListBox
    </Grid>
</Window>
Теперь реализуем наш загрузчик. Для этого создадим новый класс ShellBootstrapper в корне нашего проекта и реализуем его следующим образом:
public class ShellBootstrapper : UnityBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }

    protected override void InitializeShell()
    {
        Application.Current.MainWindow = (Window)Shell;
        Application.Current.MainWindow.DataContext = Container.Resolve<MainWindowViewModel>();
        Application.Current.MainWindow.Show();
    }

    protected override void ConfigureContainer()
    {
        Container.RegisterType<ITestModelServiceTestModelService>();
        Container.RegisterType<MainWindowViewModel>();
        base.ConfigureContainer();
    }
}
Инициализируем наше окно, конфигурируем с помощью Unity контейнера наши связи и запускаем наше представление. После всей проделанной магии осталось запустить наш загрузчик. Для этого перейдем в наш класс App.xaml.cs и переопределим метод OnStartup, как показано ниже.
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        var boostrap = new ShellBootstrapper();
        boostrap.Run();
    }
}
Полная структура проекта после реализации должна быть следующей:
Запустим наш проект, чтобы убедиться в том, что у нас все работает. Ниже вы сможете увидеть пример моего окна после запуска.

Итоги
Как видите, особо в Prism 6 ничего не изменилось. Правда, если вы использовали по каким-либо причинам интерфейс IView, вам нужно пересмотреть свою реализацию. А в целом, если вы захотите перейти с Prism 5 на Prism 6, то можете без проблем это делать. Плюс в том, что в сохранилась обратная совместимость. Правда, если вы использовали некоторые экзотические возможности Prism 5, как, например, встроенный WeakEventManager, то вам будет сложновато так как вы его использовать не сможете. Надеюсь, что эта статья даст вам некоторый толчок и убедит в том, что переход с Prism 5 на Prism 6 вполне безболезненный.

Исходники: Prism 6 sample

No comments:

Post a Comment