Pull to refresh

WPF приложения на Android, iPhone, iPad, Mac и Windows

Level of difficultyEasy
Reading time5 min
Views2.2K
WPF приложение на десктопе, планшете, телефоне
WPF приложение на десктопе, планшете, телефоне

Уже более пяти лет мы занимаемся разработкой OpenSilveropen-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:

  1. Установите расширение OpenSilver SDK.

  2. Убедитесь, что в Visual Studio установлен .NET MAUI компонент.

    .NET MAUI компонент
    .NET MAUI компонент
  3. Создайте новый OpenSilver-проект, добавив поддержку дополнительных платформ (например, Windows и Android) во время создания в окне конфигурации.

    Создание OpenSilver проекта
    Создание OpenSilver проекта
  4. В созданном решении разрабатывайте в основном проекте аналогично обычному WPF-приложению. Можно использовать наш Drag'n'Drop UI дизайнер.

    Работа над приложением
    Работа над приложением
  5. Запускайте проект либо в браузере (.Browser проект), либо как нативное приложение (.MauiHybrid проект).

    Запуск приложения
    Запуск приложения

Также можно использовать Visual Studio Code на Mac и Windows, подробнее описано в документации.

Реальный пример

Чтобы протестировать идею, мы взяли давнишнее WPF-приложение компании — календарь с событиями на месяц вперёд, и полностью мигрировали его на OpenSilver.

Миграция прошла относительно легко, поскольку проект не имел сторонних зависимостей. Однако потребовались небольшие изменения в реализации, так как OpenSilver пока не обеспечивает стопроцентную совместимость с WPF.

Дополнительным преимуществом использования MAUI является встроенная возможность публикации приложений во всех популярных магазинах приложений.

Теперь вы можете попробовать реальное смигрированное WPF-приложение:

Исходный код проекта также доступен: ToDoCalendar.

Заключение

Интеграция OpenSilver с MAUI Blazor Hybrid действительно работает, открывая широкие возможности для создания универсальных кроссплатформенных приложений. Несмотря на некоторые сложности с потоками, преимущества явно перевешивают минусы, и в результате мы получили эффективный инструмент, способный вдохнуть новую жизнь в классические десктопные приложения.

Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+4
Comments14

Articles