Это моя первая статья в Новом
году, поэтому хотелось бы ее начать с чего-то нового. А так как с Нового
года я начал потихоньку осваивать Caliburn.Micro –
фреймворк для написания приложений под WPF, Silverlight, WinRT, WP8 и т.д., используя паттерн MVVM, то первую статью я решил посвятить
именно работе с этим фреймворком. После плотной работы с Prism переход на Caliburn.Micro выглядит, словно вы изучали какой-то сложный фреймфорк с огромными возможностями и
функционалом, а тут вам дали урезанную версию этого фреймворка. Очевидные плюсы Caliburn.Micro:
- Порог вхождения для изучения Caliburn.Micro, по сравнению с Prism, ниже;
- Caliburn.Micro написан с поддержкой практически всех платформ, на которые можно писать код, используя xaml;
- По популярности этот фреймворк из-за количества платформ превосходит, наверное, все доступные на данный момент фреймворки (я не встречал более популярного бесплатного фреймфорка);
- Удобная привязка данных.
К
сожалению, есть и определенные недостатки. Например, меня очень напрягает автоматическое связывание свойств класса с контролами через x:Name. До сих пор
не могу нормально привыкнуть к такому подходу. Второой субъективный минус – это расширенный синтаксис для функций. Почему-то
ребята, спроектировавшие этот фреймворк, посчитали, что использование событий – это намного лучше, чем использование команд с интерфейсом ICommand. К сожалению, вынужден не
согласиться с таким суждением и подходом к написанию программ. Но каждый
фреймворк должен как-то выделяться, быть в чем-то уникальным, запоминающимся. Так что считаем это фишкой данного фреймворка.
При изучении какого-то нового языка или фреймворка я
стараюсь следовать простому правилу: не переносить возможности другого языка
или фреймворка на тот язык или фреймворк, который вы изучаете, иначе это не
приведет ни к чему хорошему. При изучении, например, языка C# после C попытки искать
возможности C++ в C# могут привести к тому, что вы посчитаете один язык
хуже или лучше предыдущего, основывая выводы только на сравнении. Старайтесь
изучать что-то новое в его окружении, не пытаясь проецировать то, что вы узнали
раньше, на то, что изучаете сейчас. Вспомните слова героя Джеки Чана в фильме
“Запретное царство”: “Как наполнить чашу, которая уже полна?”. В этом знаменитом
каноне о наполненной чаше кроется полезная истина, которую стоит намотать на ус
как начинающим разработчикам, так и опытным специалистам с большим багажом
знаний.
Итак, я очень постараюсь не проецировать то, что я изучил по Prism, на Caliburn.Micro. Позже подготовлю статью о схожести Caliburn.Micro с Prism
и
теми возможностями, которые лучше покрываются что одним фреймворком, и что вторым.
Начнем наш экскурс в возможности данного фреймворка. Для начала нам нужно знать,
что Caliburn.Micro
доступен, начиная с версии NET Framework 4.0. Поэтому создадим
простое десктопное приложение на WPF и назовем его FirstAppWithCaliburnMicro. Затем с
помощью Manager NuGet
Packages добавим себе ссылку на Caliburn.Micro.dll.
Актуальная
версия на момент написания статьи была 2.0.1. После того, как вы установите
данный пакет через NuGet, в ваш проект
будет добавлено сразу три библиотеки.
На рисунке эти сборки подсвечены зеленым цветом. Caliburn.Micro
–
базовая библиотека данного фреймворка со всеми интерфейсами. Caliburn.Micro.Platform – сборка специально для работы с
системой Windows. Там находятся такие классы, как WindowManager для работы с окнами, ViewLocator/ViewModelLocator и другие. Я не так давно начал изучать Caliburn.Micro,
поэтому некоторые части могу описать не настолько внятно, как написали бы
ребята, которые съели на этом зубы, но мне нравится записывать результат своей
работы в виде блога. Как оказалось, это помогает в освоении нового материала
также и читателям моего блога, что не может не радовать.
Созданный проект необходимо разбить на следующую структуру:
Структура
проекта повторяет структуру проектов с использованием паттерна MVVM (Model –View-ViewModel). В данном
примере у меня нет моделей, а используется всего одна модель
представления, поэтому создания папки Models для хранения
моделей для данного примера мне не понадобилось.
Начнем с небольшого уточнения. В Caliburn.Micro модель представления и само
представление связываются по умолчанию. Поэтому чтобы ваше представление знало
модель представления, с которой оно связано, вы должны следовать простым
правилам. Модель представления должна иметь такое же имя, как само представление, с приставкой Model. Если у вас главное окно называется MainPage, то модель представления будет иметь
название MainPageViewModel. Модель представления должна иметь
окончание “ViewModel”. Со временем вы к этому привыкнете. По
сути, в данном случае Caliburn.Micro задает вам правила именования ваших
моделей и моделей представлений. Считать это плюсом для данного фреймворка или
нет, по сути, – ваше личное предпочтение. Просто данный фреймворк продвигает подход
View-Model-First, в котором первым этапом вы добавляете
модель представления (View Model). Поэтому давайте перейдем в нашу папку ViewModels и добавим новый класс MainViewModel.
public class MainViewModel : PropertyChangedBase
{
public MainViewModel()
{
HelloWorld = "Hello
World";
}
private string _helloWorld;
public string HelloWorld
{
get { return _helloWorld; }
set
{
_helloWorld = value;
NotifyOfPropertyChange(() => HelloWorld);
}
}
//Don't use this code in
production
public void ShowMessage()
{
MessageBox.Show("Test Caliburn.Micro");
}
}
Здесь
нет ничего сверх особенного. Мы наследовались от класса PropertyChangedBase, для того чтобы
не реализовывать отдельно интерфейс INotifyPropertyChanged, а использовать
вызов NotifyOfPropertyChange, чтобы
реализовывать базовую логику с класса PropertyChangedBase, который
предоставляет обертки для данных интерфейсов.
Как видите, у нас используется одно свойство HelloWorld и метод ShowMessage с комментарием
не использовать такой подход в ваших приложениях. Вызов MessageBox с модели представления считается
нарушением паттерна MVVM, потому что
модель представления не должна управлять отображением представления. Для таких
целей нужно писать отдельные сервисы, чтобы не было нарушения разделения логики.
Теперь
перейдем в папку Views, перенесем туда
наше созданное по умолчанию главное окно MainWindow.xaml и переименуем его в MainView.xaml.
Примечание. По правилам Caliburn.Micro нам нужно было
бы назвать наше главное окно Main.xaml, но мне это имя не нравится, а поскольку Caliburn.Micro нормально
связывает названия с приставкой View, я решил
использовать такое название.
В
это окно я добавил один контрол для отображения сообщения и кнопку для показа MessageBox.
<Window x:Class="FirstAppWithCaliburnMicro.Views.MainView"
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>
<StackPanel Orientation="Vertical">
<TextBlock x:Name="HelloWorld" />
<Button x:Name="ShowMessage" Content="Show Message"/>
</StackPanel>
</Grid>
</Window>
Если
вы посмотрите внимательно на код, то я не указал ни одной строчки байдинга
явно, и самое интересно, из-за чего мне и нравится Caliburn Micro, – то, что это
реально работает. Не знаю, почему в примерах в инете, которые объясняют
использование Caliburn в своих проектах, нет ни слова об этом
для начальных проектов. Обычно все это показывают со второй темы по данному
фреймворку. Но я решил немного соригинальничать и показать, как работает
привязка данных на простом примере. Для простых контролов, как, например TextBox или Button
или другие простые контролы, как в нашем примере, если мы укажем имя контрола x:Name таким же, как
свойство в модели представления, то оно будет вызвано автоматически. Аналогично
для функции, которая для кнопки Button, по сути, делает
то же самое, поскольу имя контрола ShowMessage совпадает с
именем функции в модели представления MainViewModel. Теперь нам
осталось реализовать загрузчик, который инициализирует начальные настройки для
запуска приложения. В отличие от версии Сaliburn.Micro 1.5.0, работа с загрузчиком претерпела небольших изменений, о которых вы можете узнать здесь: Upgrading
Caliburn Micro from 1.5 to 2.0 for a WPF application. А теперь добавим сам загрузчик в наш проект. Для этого создадим новый класс, который
назовем ShellBootstrapper, и наследуем его
от BootstrapperBase, как показано в примере ниже.
public class ShellBootstrapper : BootstrapperBase
{
public ShellBootstrapper() : base(true)
{
Initialize();
}
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<MainViewModel>();
}
}
Как
видите, этих пару строчек достаточно для запуска нашего приложения. Теперь
осталось создать объект данного класса в App,
для того чтобы инициализировать начальные значения. Для этого мы сделаем всю
настройку в xaml. Переходим в наш файл App.xam и в первую очередь удаляем StartupUri, поскольку запуском главного окна
будет заниматься наш загрузчик. И слегка модифицируем наш xaml код, как показано ниже в примере.
<Application x:Class="FirstAppWithCaliburnMicro.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:firstAppWithCaliburnMicro="clr-namespace:FirstAppWithCaliburnMicro">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<firstAppWithCaliburnMicro:ShellBootstrapper x:Key="Bootstrapper" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Вы можете сделать то же самое через код, переопределив метод OnStartup класса App.
Смотрите, как вам удобнее использовать данный подход. Все!!!
Этого достаточно, чтобы запустить наше приложение и убедиться, что оно работает.
А также убедиться, что если мы нажмем на кнопку ShowMessage, то у нас все будет работать.
Думаю, для начальной работы с Caliburn этой статьи будет достаточно. Надеюсь, вам
понравились возможности данного фреймоворка. В следующих статьях мы рассмотрим
еще новые возможности данного фреймворка, которых не так уж мало. Надеюсь, что
статья показалась не очень сухой. Это первая статья в Новом году,
поэтому возможны некоторые недочеты, которые вызваны длинным отдыхом и ленью браться
за изучение чего-то нового.
No comments:
Post a Comment