Сегодня повсюду все говорят о HTML5. Я сам недавно выступал на
Датской конференции разработчиков 2012 года по Windows Phone и HTML5 . Я понял суть и вижу мощь и красоту HTML5. Но, насколько я вижу, HTML5 пока еще не совсем готов, а что касается мобильных приложений, я бы всегда выбрал написание собственного приложения, которое в полной мере использует преимущества платформы, а не только приложения, запускаемого в браузере, даже если Компонент браузера размещается в собственном приложении. Я думаю, что разработчики действительно должны научиться ценить платформу больше.
В этой статье я хотел бы объяснить, как интегрировать HTML5 + Javascript в приложение Windows Phone, а также продемонстрировать, как вызывать метод .NET из Javascript и как вызывать метод Javascript из .NET.
Итак, вот что нам нужно сделать, чтобы начать:
- Создайте приложение Windows Phone Silverlight
- Добавить компонент WebBrowser на главной странице
- Установите для свойства IsScriptEnabled компонента WebBrowser значение true
- Добавьте обработчик события в событие ScriptNotify компонента WebBrowser
- Создайте в проекте папку с именем HTML и добавьте в нее ресурсы HTML, Javascript и Stylesheet.
- Напишите код для копирования ресурсов, связанных с HTML, в IsolatedStorage
- Установите источник компонента WebBrowser на главную страницу HTML
Просто не так ли?
Как это работает
Шаги, описанные выше, действительно кажутся довольно простыми, и да, это действительно так. Для вызова Javascript на хосте элемента управления WebBrowser мы можем использовать метод
window.external.notify () . Это тот же самый подход для выполнения кода Javascript кода в хост-приложении на других платформах. Метод
window.external.notify () принимает строку, которая может содержать метаданные, описывающие, что вы хотите, чтобы хост делал. А для кода .NET для выполнения кода Javascript мы используем метод
InvokeScript () элемента управления WebBrowser.
InvokeScript () Метод принимает строковый параметр, который описывает метод Javascript для выполнения, и коллекцию строк, которые описывают аргументы, которые должны быть переданы методу Javascript для выполнения. Если метод, который будет вызывать функцию javascript с хоста, выполняется в потоке, не являющемся пользовательским интерфейсом (рабочий поток), тогда лучшим подходом к использованию этого метода является вызов
InvokeScript («eval», «methodName (args1, args2, args3) «) вместо передачи имени метода, который будет вызван в качестве первого аргумента метода.
Вот схема, которую я использовал в DDC 2012, которая иллюстрирует процесс, упомянутый выше:
В этом примере у нас будет приложение, в котором размещена страница HTML5, отображающая информацию о памяти устройства (как показано на снимке экрана ниже).
И вот код …
Default.html (HTML5 + Javascript)
Приведенный ниже код будет использоваться как локальный HTML-файл, который нужно скопировать в изолированное хранилище. Давайте поместим это в папку с именем HTML
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=480, height=800, user-scalable=no" /> <meta name="MobileOptimized" content="width" /> <meta name="HandheldFriendly" content="true" /> <title>HTML5 and Windows Phone 7</title> <style> body { color: White; background-color: Black; font-family: 'Segoe WP Semibold'; text-align: left; } h3 { font-size: 20pt; } input { color: #ffffff; background-color: #000000; border: 2px solid white; vertical-align: baseline; font-size: 17pt; min-width: 40px; min-height: 40px; margin: 5; } </style> </head> <body onload="onLoad()"> <div> <h3> Current memory usage:</h3> <input id="memoryUsage" type="text" value="0" /> <h3> Memory usage limit:</h3> <input id="memoryUsageLimit" type="text" value="0" /> <h3> Peak memory usage:</h3> <input id="peakMemoryUsage" type="text" value="0" /> <h3> Total memory:</h3> <input id="totalMemory" type="text" value="0" /> </div> <script type="text/javascript"> function onLoad() { window.external.notify("getMemoryUsage"); } function getMemoryUsageCallback(memoryUsage, memoryUsageLimit, peakMemoryUsage, totalMemory) { document.getElementById("memoryUsage").value = memoryUsage; document.getElementById("memoryUsageLimit").value = memoryUsageLimit; document.getElementById("peakMemoryUsage").value = peakMemoryUsage; document.getElementById("totalMemory").value = totalMemory; } </script> </body> </html>
MainPage.xaml
Приведенный ниже код является главной страницей приложения Silverlight, в котором будет размещен контент HTML.
<phone:PhoneApplicationPage x:Class="PhoneApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True" Loaded="PhoneApplicationPage_Loaded"> <Grid x:Name="LayoutRoot" Background="Transparent"> <phone:WebBrowser Name="browser" IsScriptEnabled="True" Source="HTML/Default.html" ScriptNotify="browser_ScriptNotify" /> </Grid> </phone:PhoneApplicationPage>
MainPage.xaml.cs
А вот код файла xaml
public partial class MainPage : PhoneApplicationPage { public MainPage() { InitializeComponent(); } private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) { using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication()) { if (!store.DirectoryExists("HTML")) store.CreateDirectory("HTML"); CopyToIsolatedStorage("HTML\\Default.html", store); } } private static void CopyToIsolatedStorage(string file, IsolatedStorageFile store, bool overwrite = true) { if (store.FileExists(file) && !overwrite) return; using (Stream resourceStream = Application.GetResourceStream(new Uri(file, UriKind.Relative)).Stream) using (IsolatedStorageFileStream fileStream = store.OpenFile(file, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { int bytesRead; var buffer = new byte[resourceStream.Length]; while ((bytesRead = resourceStream.Read(buffer, 0, buffer.Length)) > 0) fileStream.Write(buffer, 0, bytesRead); } } private void browser_ScriptNotify(object sender, NotifyEventArgs e) { var response = new object[] { DeviceStatus.ApplicationCurrentMemoryUsage, DeviceStatus.ApplicationMemoryUsageLimit, DeviceStatus.ApplicationPeakMemoryUsage, DeviceStatus.DeviceTotalMemory }; browser.InvokeScript("getMemoryUsageCallback", response.Select(c => c.ToString()).ToArray()); } }
В приведенном выше коде происходит то, что при загрузке главной страницы html-ресурсы копируются в изолированное хранилище и загружаются в компонент веб-браузера в виде локального файла. Когда
запускается ScriptNotify , приложение Silverlight получает информацию о памяти, используя
класс DeviceStatus, и передает эту информацию обратно компоненту WebBrowser, вызывая метод getMemoryUsageCallback () с помощью метода
InvokeScript () компонента WebBrowser.
Приведенный выше пример является очень простым и наивным. но он демонстрирует что-то, что может обеспечить бесконечные возможности взаимодействия платформы. Я надеюсь, что вы нашли это полезным.
Вы можете получить полный исходный код, приведенный выше, здесь: