Как сделать Prism (MEF) приложение на Silverlight

ru-RU | создано: 13.07.2011 | опубликовано: 13.07.2011 | обновлено: 01.01.2018 | просмотров за всё время: 5951

Довольно продолжительное время не занимался проектами на Silverlight. Поэтому руки не доходили до Prism. Короче, забыл напрочь про то как из простого Silverlight-приложения сделать приложение на Prism, да еще и такое, которое использует MEF. Вот как раз в этой статье буду вспоминать, а за одно и последовательно описывать как этот сделать.

Создаем проект Silverlight

Итак, для начала скачиваем библиотеку Prism с официального сайта. На момент написания статьи версия предложенная для скачивания была Prism 4.0 November 2010. Теперь создаем новый Silverlight-проект.

image

Название выбрано, папка сохранения проекта указана, нажимаю Ok. В следующем окне мастера указываю, что не надо создавать Web проект, отключив соответствующую галку. Подтверждаю выбор. Начало положено. Теперь сразу же удаляю файл MainPage.xaml, потому как мне он не пригодится. Надо добавить сборки Prism в проект:

image

Так как я хочу использовать MEF, поэтому отмечаю еще и Microsoft.Practice.Prism.MefExtentions.dll - сборка расширений. Создаю новый Bootstrapper, который является “стартером” приложения. И прежде чем начать с ним работу создам-ка я Shell для моего проекта. Добавляю в проект новый Silverlight User Control под именем Shell.xaml. Теперь возвращаюсь к “стартеру”. Унаследуюсь от MefBootstrapper, переопределю метод CreateShell(), ConfigureAggregateCatalog() и InitializeShell(). Вот как теперь выглядит мой стартер:

public class Bootstrapper : MefBootstrapper
{
   protected override void ConfigureAggregateCatalog()
   {

     this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
   }
  
    protected override DependencyObject CreateShell()
    {
        return this.Container.GetExportedValue<Shell>();
    }
  
    protected override void InitializeShell()
    {
        base.InitializeShell();
        Application.Current.RootVisual = (Shell)this.Shell;
    }
}

Хорошо… хорошо, потому что не компилируется приложение, но я знаю почему (файл MainPage.xaml был удален). Чтобы началось всё компилироваться сделаем следующее. Добавляю еще одну сборку в проект: System.ComponentModel.Composition.dll:

using System.ComponentModel.Composition.Hosting;

Это потому, что этого требует MEF. Теперь требуется внести некоторые изменения в файле App.xaml.cs. Надо же как-то указать что является стартовым пользовательским интерфейсом:

private void Application_Startup(object sender, StartupEventArgs e)
{
    //this.RootVisual = new MainPage();
    Bootstrapper starter = new Bootstrapper();
    starter.Run();
}

Надеюсь, понятно, что я сделал. Компилирую… Ошибок нет, но при запуске получаю ошибку… А-а-а-а!!! Надо же поставить атрибут экспорта на классе Shell.

[Export]
public partial class Shell : UserControl
{
   public Shell()
   {
       InitializeComponent();
   }
}

Вот теперь проект запустился! И хоть не очень приятно смотреть на пустой экран, сделаю небольшое лирическое отступление.

Экспорт шаблона приложения

Дело в том, что начинать программировать любое приложение на Prism нужно будет почти всегда одинаково так, как я только что показал. То есть, по большому счёту, данный пример на данный момент является практически готовым шаблоном для всех последующих проектов. А значить если нажать в меню File –> Export Template:

image

И далее, следуя подсказкам мастера сохранения шаблона, можно избежать повторений выше проделанных операций, сохранив текущий проект как шаблон проекта. Если Вы сохраните сей шаблон, то в следующий раз можно будет просто выбрать его из списка предложенных шаблонов проектов.

Хочется зрелищ

Белый экран – не самый приятный вид для работающего приложения. Надо что-то отобразить, а за одно, покажу какие дальнейшие действия можно предпринять, чтобы увидеть в действии и Prism, и MEF.

Можно использовать набор библиотек Prism по-разному. Я покажу пример с использованием регионов. Для этого открою Shell и добавлю требуемый namespace, чтобы добавить в разметку регион:

xmlns:prism=http://www.codeplex.com/prism

Теперь добавлю контрол ContentControl и помечу его:

<Grid x:Name="LayoutRoot" Background="White">
        <ContentControl prism:RegionManager.RegionName="MainRegion" 
                        VerticalContentAlignment="Stretch"
                        HorizontalContentAlignment="Stretch"
                        VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
</Grid>

Хорошо. Нужно теперь в этот регион что-нибудь запихнуть. Создаю новый визуальное представление (SimpleView.xaml), чтобы было на что запихивать. Представление элементарно! Я изменил цвет фона и этого достаточно, чтобы увидеть, что View была успешно подключена:

<UserControl x:Class="SilverlightPrimApplication.SimpleView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    MinHeight="300" MinWidth="400" >

    <Grid x:Name="LayoutRoot" 
                Background="OrangeRed" 
                VerticalAlignment="Stretch" 
                HorizontalAlignment="Stretch">
    </Grid>
</UserControl>

В Shell надо получить экземпляр IRegionManager и самой SimpleView, а потом положить одно в другое. Сначала помечаю представление атрибутом экспорта:

[Export]
public partial class SimpleView : UserControl
{
   public SimpleView()
   {
       InitializeComponent();
   }
}

В файле Shell.xaml.cs настраиваю импорты:

[Import]
public IRegionManager RegionManager { get; set; }

[Import]
public SimpleView View { get; set; }

Теперь надо подписаться на событие, которое выстреливает когда экспорты наполнены данными, для этого класс Shell реализую интерфейс IPartImportsSatisfiedNotification:

[Export]
public partial class Shell : UserControl, IPartImportsSatisfiedNotification
{
   ...
}

Ну, и наконец, заключающий сею статью код:

public void OnImportsSatisfied()
{
    RegionManager.Regions.CollectionChanged += (OnRegionsReady);
}

private void OnRegionsReady(object sender, NotifyCollectionChangedEventArgs e)
{
    IRegion region = RegionManager.Regions["MainRegion"];
    object view = View;
    region.Add(view, "simple");
    region.Activate(view);
}

Готово. Компиляция, запуск… Успешно! Передо мной IE ярко оранжевого цвета. Что и требовалось доказать. Ура! Спасибо за внимание. И да прибудет с вами сила MEF!

Комментарии к статье (4)

03.08.2011 12:52:00 DEBIL

У меня ничего не получилось! MEF - ГОВНО! Блеадь!!!

05.09.2011 15:30:00 dem

Спасибо, за статью, тока начал разбираться прояснил пару непонятных для себя вопросов

25.11.2011 13:31:00 Алексей Бурдыкин

все просто супер - отлично работает, не перегружено лишним кодом. Упражнение позволяет понять идею в чистом виде.

20.01.2017 20:24:51 Бухой

Спасибо ))) Хоть и бухой но сделал