
Уже более пяти лет мы занимаемся разработкой OpenSilver — open-source фреймворка, который позволяет переносить приложения на базе WPF и Silverlight в современный веб. Проект стабильно развивается, активно используется в корпоративной среде, и недавно мы задумались о том, как расширить возможности наших пользователей и запустить существующие приложения ещё и на iOS и Android.
Поскольку под капотом OpenSilver использует платформу Blazor, логичным шагом стала интеграция с .NET MAUI Blazor Hybrid. В этой статье я расскажу, как прошла интеграция и какие результаты мы получили на практике. Забегая вперёд, скажу, что результатом мы остались очень довольны!
Краткий обзор MAUI Blazor Hybrid и OpenSilver
.NET MAUI Blazor Hybrid позволяет запускать Blazor веб-приложения в нативной оболочке для Windows, macOS, iOS и Android. Технически это реализовано благодаря компоненту WebView, встроенному в нативный MAUI-контейнер. Таким образом, приложение выглядит и ощущается нативным, сохраняя пользовательский интерфейс и логику, созданные на HTML, CSS и C#.
Основное преимущество Blazor Hybrid — отсутствие необходимости в отдельном сервере или WebAssembly: весь код выполняется локально в единой среде .NET. Это упрощает разработку и позволяет использовать все возможности .NET MAUI, включая доступ к API платформы, работу с файлами, GPS, уведомления и другие нативные функции устройств.
OpenSilver занимается транспиляцией XAML (подмножество WPF) в C#, выполнением кода, а затем генерацией HTML, CSS и JavaScript для отображения интерфейса во время выполнения программы. И тут пазл сложился! Мы берем платформу MAUI Blazor Hybrid, запускаем там C# код и показываем наш интерфейс в предоставленном WebView.
Вроде бы все идеально, однако здесь нас ожидал первый сюрприз.
Проблемы с потоками
Нам критично в некоторых случаях выполнять JavaScript-код синхронно. К сожалению, WebView поддерживает только асинхронные вызовы. Чтобы решить этот вопрос мы были вынуждены создать отдельный поток для OpenSilver-части приложения, поэтому формально у нас теперь два UI-потока: основной UI-поток MAUI и UI-поток OpenSilver.
Достаточно скоро становится очевидно, что для OpenSilver потока нам требуется собственный Dispatcher. Поскольку MAUI не позволяет создать два потока с Dispatcher'ом, мы интегрировали свою реализацию.
Другая важная задача — обращение к системным API, которые требуют выполнения из главного MAUI UI-потока. Здесь MAUI предоставляет стандартный путь и мы можем смело сделать такой вызов. Правда, нам нужно понимать, где какой код будет выполнен.
Давайте рассмотрим этот вопрос на примере получения координат:
//Переключаемся на MAUI UI поток
MainThread.BeginInvokeOnMainThread(async () =>
{
//Получаем необходимый доступ
var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
if (status != PermissionStatus.Granted)
{
status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
}
if (status == PermissionStatus.Granted)
{
//Получаем координаты
var request = new GeolocationRequest(GeolocationAccuracy.Medium);
var location = await Geolocation.Default.GetLocationAsync(request);
if (location != null)
{
//Переключаемся назад на OpenSilver UI поток
Dispatcher.BeginInvoke(() =>
{
TB.Text = location.ToString();
});
}
}
else
{
//Переключаемся назад на OpenSilver UI поток
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Location permission denied.");
});
}
});
Переключение между потоками — пожалуй, единственное серьёзное неудобство этого подхода. Однако, поняв идею двух потоков и Dispatcher'ов, работать становится вполне комфортно.
Нативные API
Одно из главных преимуществ MAUI Blazor Hybrid — это простой и прямой доступ к нативным API устройств на всех поддерживаемых платформах. Ваше приложение, написанное на OpenSilver, теперь легко может использовать такие функции, как работа с файлами и папками устройства, доступ к камере, геолокации и датчикам, отправка локальных уведомлений, а также взаимодействие с системными диалогами и буфером обмена, как любое полноценное нативное приложение!
Например, вы можете быстро интегрировать функциональность съемки фотографий или сканирования QR-кодов, используя камеру устройства. Или предоставить пользователям возможность сохранять файлы напрямую на диск смартфона или компьютера. Вся работа с этими возможностями происходит непосредственно из C# кода, без необходимости писать специфические реализации отдельно под каждую платформу. Это существенно ускоряет разработку и делает ваши OpenSilver-приложения по-настоящему универсальными.
Сторонние библиотеки
Возникает вопрос, как работать со сторонними библиотеками в данном подходе.
Библиотеки без UI-компонентов используются без проблем как есть.
С UI-библиотеками сложнее — их требуется предварительно мигрировать на OpenSilver. Сначала проверьте доступность уже смигрированных библиотек в NuGet, если таких нет, придётся мигрировать самостоятельно. Для этого нужен исходный код, и собрать библиотеку как OpenSilver версию.
Как попробовать?
Пожалуй, проще всего будет попробовать в Visual Studio 2022 на Windows:
Установите расширение OpenSilver SDK.
-
Убедитесь, что в Visual Studio установлен .NET MAUI компонент.
.NET MAUI компонент -
Создайте новый OpenSilver-проект, добавив поддержку дополнительных платформ (например, Windows и Android) во время создания в окне конфигурации.
Создание OpenSilver проекта -
В созданном решении разрабатывайте в основном проекте аналогично обычному WPF-приложению. Можно использовать наш Drag'n'Drop UI дизайнер.
Работа над приложением -
Запускайте проект либо в браузере (.Browser проект), либо как нативное приложение (.MauiHybrid проект).
Запуск приложения
Также можно использовать Visual Studio Code на Mac и Windows, подробнее описано в документации.
Реальный пример
Чтобы протестировать идею, мы взяли давнишнее WPF-приложение компании — календарь с событиями на месяц вперёд, и полностью мигрировали его на OpenSilver.
Миграция прошла относительно легко, поскольку проект не имел сторонних зависимостей. Однако потребовались небольшие изменения в реализации, так как OpenSilver пока не обеспечивает стопроцентную совместимость с WPF.
Дополнительным преимуществом использования MAUI является встроенная возможность публикации приложений во всех популярных магазинах приложений.
Теперь вы можете попробовать реальное смигрированное WPF-приложение:
Исходный код проекта также доступен: ToDoCalendar.
Заключение
Интеграция OpenSilver с MAUI Blazor Hybrid действительно работает, открывая широкие возможности для создания универсальных кроссплатформенных приложений. Несмотря на некоторые сложности с потоками, преимущества явно перевешивают минусы, и в результате мы получили эффективный инструмент, способный вдохнуть новую жизнь в классические десктопные приложения.
Комментарии (13)
MagMagals
12.05.2025 06:34Зачем, когда есть AvaloniaUI?
JacobL Автор
12.05.2025 06:34Чтобы не было монополии. У пользователя должен быть выбор :)
MagMagals
12.05.2025 06:34выбор в чем? для пользователей не имеет разницы на чем было сделано решение. из сообщения выше, вы теперь столкнулись с тем что нужно как-то сделать под linux версию, и нашли костыль под который придется адаптироваться. хорошо когда исследования кто-то оплачивает, но плохо когда задачу решают не заточенными инструментами
Einherjar
12.05.2025 06:34Я не очень понял чем это лучше чем просто MAUI as is?
JacobL Автор
12.05.2025 06:34Самое большое преимущество — возможность запускать приложение еще в браузере! Для кого-то плюс это то, что версия XAML из WPF. И, в целом, принципиально другая реализация рендеринга, чем в MAUI. Так что, если по каким-то причинам не устраивает рендеринг в MAUI, то можно воспользоваться нашей реализацией.
Einherjar
12.05.2025 06:34Для кого-то плюс это то, что версия XAML из WPF
XAML из WPF это нигде не самоцель. Любое легаси на нем держат две вещи - сторонние библиотеки (зачастую платные/закрытые) и обилие всяких костылей и хаков. Если при переходе на что то "похожее на WPF"/"якобы совместимое c WPF"/whatever что-либо из этого отваливается, то количество трудозатрат становится сравнимо с переписыванием с нуля на любой другой фреймворк. А различия в синтаксисе это не самая большая проблема.
HOMPAIN
12.05.2025 06:34Слишком много одинаковых UI для C#. Непонятно что выбрать и все проекты сырые с кучей багов.
Siemargl
12.05.2025 06:34Что с производительностью визуала?
JacobL Автор
12.05.2025 06:34Зависит от интерфейса. Можно сверстать интерфейс, который будет медленно работать. В этом плане приложение календарь из статьи — хороший пример. Там много ячеек, которые надо отрисовать. Можете попробовать на разных платформах!
IL_Agent
12.05.2025 06:34Было бы здорово увидеть статью, в которой проводится сравнение актуальных кроссплатформенных xaml фреймворков
peacemakerv
А Линух ?
TerekhinSergey
так поверх MAUI же, а там линукс не завезли и не завезут походу
JacobL Автор
Мы тоже пришли к этому вопросу! Поэтому сделали еще один способ запуска. Через Photino. Мне Photino очень понравился. Единственное - нельзя использовать нативные MAUI API, так что придется это еще дополнительно реализовать под линукс. Кстати, пример с ToDoCalendar также имеет возможность запускаться на линуксе через Photino.