.Net: женим Portable Library и UI

Источник: habrahabr
Lincoln6Echo

Один контрол на всех, и все на одного: WPF, Silverlight 4-5, WinPhone 7-8, Windows Store App (x86, x64, ARM)

Сразу дискламер - это не Розеттский камень, а лишь хитрость, которая поможет, если у вас есть UserControl, почти идентичный для всех платформ.

Бонус - видео процесса разработки в конце статьи - статья простая и короткая, а видео 8 минут отличной музыки. Не у всех есть Windows8, многим наверное будет просто любопытно увидеть процесс в W8 + VS2012, поэтому заморочался.

Нам подарили Portable Library - отличная штука, сразу для всех платформ. Но, есть и ложка дёгтя - почти ничего, кроме числомолотилки и бизнес-процессов с этим не сварить, поддерживаемые неймспейсы подвели. 
Эта штука не только не знает что такое XAML, но не знает даже что такое Point! Куда уж проще, две координаты, X и Y - но это проблема, и предмет отдельного обсуждения с лучами ненависти к индусам и бардаку архитекторов.

Итак, мое первое знакомство с Portable Library случилось не лучшим образом - оно напомнило мне случай, когда девушка поднялась ко мне в диджейку и передразнила Аллегрову: "Я ждала тебя, так ждала, ты был мечтою моей фрустральною! " (Но там боссы корпоратива заказывали музыку..) 

Но я придумал, как побороть проблему с PL, которая назревала у моей будущей статьи про HSL Color Dialog, и эта статья - приставка к следующей статье, и туториал. 
Сразу оговорюсь, не во всех случаях поможет, в WinRT например нет Label, но везде есть TextBlock, "специфику платформ" придется соблюдать.

Краткое описание видео:

1. Создаем солюшн, и в нем проект WPF UserControl. Это будет наша песочница, именно в ней мы будем создавать и редактировать будущий универсальный контрол(ы). Сам по себе этот проект в продакшне не нужен, так-что лично я назвал его Sandbox и забил.
1а. Нас интересует только голый XAML. Удаляем из XAML наименование класса, удаляем сам файл .cs.
1б. Редактируем XAML, и он самое важное, это рабочий файл, годный для работы GUI-дизайнерам, в Бленде например.

2. Создаем проект Portable Library, выбираем из диалога нужные версии всего, что нам надо. 
2а. В проект PL добавить XAML с контролом из песочницы. Важно: добавить как Link на файл. Иначе все GUI-изменения в проекте песочницы над контролом придется руками перетаскивать каждый раз. 
2б. Добавленный линк на файл сделать Embedded Resource.
2в. Embedded Resource достается и передается в райнтайме так:
public class Class1 { public Stream GetXaml() { string[] names = this.GetType().Assembly.GetManifestResourceNames(); Stream s = this.GetType().Assembly.GetManifestResourceStream(names[0]); return s; } } Важно: PL не знает, что на самом деле передает, а принимающие приложения не знают достоверно, что это валидный XAML, так-что в продакшне важно обложиться проверками! Я их опустил, ради простоты кода.

3. Создаем любой GUI-проект из семейства WPF-родственничков. Работающая киллер-фича в этой многоплатформенности - парсинг XAML в райнтайме. Пользуемся ей примерно так:
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) { Class1 class1 = new Class1(); DependencyObject importedXaml; using (Stream stream = class1.GetXaml()) { importedXaml = XamlReader.Load(stream) as DependencyObject; stream.Close(); } UserControl control = importedXaml as UserControl; rootGrid.Children.Add(control); }Еще раз напоминаю о проверках.

Итого:
Наша PСL-библиотека выступила как прокси, передающая контрол из песочницы любой платформе WPF-семейства, воспользовавшись своей уникальной способностью в одиночку быть подгруженной любой из них. Ирония в том, что она не в курсе, что это сделала. И при этом у нас остался проект в песочнице с контролом, над которым могут трудиться GUI-дизайнеры.
Да, костыль конечно. Но и польза есть, Portable Library годится для передачи чего угодно (например иконок) как единый источник для всех платформ.

Далее, под каждую платформу уже можно завести Dictionary с описанием стилей для элементов. При необходимости, если дефолт платформы не подошел. 

Видео ниже охватывает все платформы, но порезано и ускорено до 8 минут (оригинальный скринкаст был ~45 минут). Vimeo дал гароздо более четкую картинку на том-же разрешении. Youtube "из корбки" показывает HD, но гораздо хуже качеством.

Прямые ссылки:
Vimeo
Youtube


Страница сайта http://www.interface.ru
Оригинал находится по адресу http://www.interface.ru/home.asp?artId=32293