Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
03.11.13 / ! / Создаем контекстно.doc
Скачиваний:
54
Добавлен:
08.06.2015
Размер:
2.64 Mб
Скачать

Создаем контекстно-зависимое WPF-приложение #024 – Знакомство с WPF/E #023 – Введение в WPF, reloaded… #022 Введение в Microsoft Interactive Designer RC1 #021 Применение 3D в WPF - Часть 2 #020 Применение 3D в WPF - Часть 1 #019 Введение в возможности 3D на WPF #018 Размещение контрола NET 2.0 на форме WPF #017 Первое Web-приложение / Подробнее о Grid / Элемент Frame #016 EXE, XBAP, XAML? - Все равно!

Создаем контекстно-зависимое WPF-приложение

Начинаем цикл публикаций, призванных помочь начинающим программистам в создании контекстно-зависимых приложений для Windows 7. Об этом много говорили на PDC да и мы неоднократно писали о этом новом классе приложений. Пользователи Windows 7 build 6801 могли заметить появление в гаджете погоды опции автоматического определения местоположения компьютера. И сегодня у вас появилась уникальная возможность попробовать себя в создании подобных приложений. Я решил немного поиграть с Windows Location Platform, входящей в состав Windows 7 build 6801, которая была роздана посетителям конференции PDC 2008, и решил попробовать создать свое WPF-приложение, которое показывало бы карту Virtual Earth и мое местоположение на ней. В сборке 6801 всем СОМ-классы Location API обозначены как ThreadingModel = Free (MTA). Поэтому, для того чтобы вызвать их из другой потоковой модели (STA), придется прибегнуть к промежуточным классам. Похоже, что сборка, генерируемая VS (LocationDispLib.dll), не включает в себя эти самые промежуточные классы для COM-распределения. Таким образом, для получения доступа к Location API нам необходимо использовать другой поток, который позволит использовать эти данные в нашем WPF-приложении. Что нужно для создания приложения

  • Windows 7 build 6801

  • Visual Studio 2008 SP1

  • RibbonControlsLibrary (CTP)

  • WPF-контрол Virtual Earth от Майка Толти (Mike Taulty)

  • Virtual GPS (от HOL с PDC)

Сценарии, которые позволяет реализовать приложение

  • Показывать карту на базе местоположения пользователя

  • Показывать схему движения, автоматически обновляя данные

  • Очищать карту

Запускаем приложение. Нажимаем на кнопку Show Me on Map, Windows Location Platform получает координаты, приложение отмечает текущее местоположение на карте. Приложение отслеживает перемещения и ежесекундно отмечает их. Как это реализовано Windows Location Platform API представлены COM- и Win32-объектами. Для упрощения программирования мы воспользуемся COM-версией API, которая внедрена в файл LocationDisp.dll в папке %Windir%\System32\ (в x86-версии). Для использования данного API нам необходимо добавить в проект ссылку на эту библиотеку. 1. Так как API запускаются в режиме MTA, а основное WPF-приложение в STA, нам нужно использовать отдельный поток для того, чтобы наше приложение могло получить информацию от API.

  • BackgroundWorker m_worker предназначен для обработки изменения местоположения, а второй BackgroundWorker m_workerStatus добавляем в определение Window1:

Код:

BackgroundWorker m_worker = new BackgroundWorker(); BackgroundWorker m_workerStatus = new BackgroundWorker(); private LatLongReport m_report = new LatLongReport(); private LocationPlatformStatus m_status = new LocationPlatformStatus(); DispatcherTimer m_timerAutoTracking = new DispatcherTimer(); DispatcherTimer m_timerLocPlatformStatus = new DispatcherTimer(); bool m_useAutoTracking = false;

Таймеры будут использоваться для обработки изменения местоположения (m_timerAutoTracking). LatLongReport - .NET упаковщик для класса DispLatLongReport из Interop.LocationDisp.dll, которая была создана из LocationDisp.dll силами Visual Studio. Она необходима для того, чтобы несколько упростить COM-функцию, вызываемую в .NET-приложении.

  • В конструкторе Window1 мы инициализируем и фоновые исполнители, и таймеры:

Код:

public Window1() { InitializeComponent(); m_worker.DoWork += new DoWorkEventHandler(worker_DoWork); m_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); m_workerStatus.DoWork += new DoWorkEventHandler(m_workerStatus_DoWork); m_workerStatus.RunWorkerCompleted += new RunWorkerCompletedEventHandler (m_workerStatus_RunWorkerCompleted); m_timerAutoTracking.Interval = new TimeSpan(0, 0, 0, 0, 1000); m_timerAutoTracking.Tick += new EventHandler(m_timer_Tick); m_timerLocPlatformStatus.Interval = new TimeSpan(0, 0, 0, 0, 1000); m_timerLocPlatformStatus.Tick += new EventHandler(m_timerLocPlatformStatus_Tick); // enabling Status Timer m_timerLocPlatformStatus.Start(); }

Здесь мы просто инициализировали асинхронные обработчики событий DoWork и RunWorkerCompleted для обоих исполнителей Background Worker, настров интервал в 1 секунду для таймеров и обработчиков их событий.

  • Вызов Windows Location Platform API Нажав кнопку Show Me On Map, пользователь инициализирует в приложении соответствующую команду и она запускает асинхронный исполнитель Background Worker m_worker:

Код:

public void ShowMeOnMapCommand_Executed(object sender, ExecutedRoutedEventArgs e) { try { m_worker.RunWorkerAsync(); } catch { // some times it can't do the job at 1 sec } }

Тут, однако, есть маленькая проблема. Так как мы не подписываемся на события через Location API, но при этом вызываем их, используя таймеры, исполнители Background Worker могут столкнуться с проблемой, при которой они не успели завершить свою работу. Чтобы не усложнять приложение, я решил добавить здесь блок. RunWorkerAsync() включает событие DoWork() из фонового исполнителя m_worker:

Код:

void worker_DoWork(object sender, DoWorkEventArgs e) { LatLongReportFactoryClass factory = new LatLongReportFactoryClass(); m_report = new LatLongReport(factory.LatLongReport); }

Именно здесь происходит реальное обращение к Windows Location API. То есть нам необходимо сослаться на LatLongReportFactoryClass и получить от него LatLongReport, который и будет использоваться в приложении. В действительности, первое, что нам необходимо сделать - проверить поле LatLongFactoryClass.Status, чтобы убедится, что сенсоры доступны и работают.

  • Когда фоновый исполнитель m_worker завершит получение LatLongReport, нам нужно создать на карте новый PushPin, дать ему текущие координаты и показать на карте.

Код:

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { //Cancelled } else if (e.Error != null) { //Exception Thrown } else { //Completed PushPin pushPin = new PushPin(); pushPin.Latitude = m_report.Latitude; pushPin.Longitude = m_report.Longitude; t his.VirtualEarth.PushPins.Add(pushPin); pushPin.CenterInMap(); } }

В данном методе мы центрируем карту, чтобы созданная отметка показывалась по центру Virtual Earth. В случае если сенсоры присутствуют, включены и доступны, нажатие кнопки Show Me on Map покажет в центре карты Virtual Earth нашу позицию.

2. Для реализации автоматического обновления местоположения мы используем таймер Dispatcher Timer m_timer, который автоматически будет запускать Background Worker m_worker для получения информации о местоположении. Для этого мы просто добавим в обработчик вызова кнопки Show/Stop showing My Trip on Map Automatically вызов Start/Stop m_timer, а для отметки на карте - m_worker.RunWorkerA. 3. Чтобы очистить карту, требуется вызвать метод “Clear” из коллекции контролов “PushPins”. Теперь вы знаете, как вызывать Windows 7 Location Platform API с целью получить информацию о местоположении пользователя, и использовать ее в WPF-приложении. Вот, собственно, и все. В следующий раз мы поговорим о том, как проверить статус платформы, о том, что делать в случае, если доступ запрещен, и что делать с провайдером, используемым по умолчанию. Источник: http://blogs.msdn.com/semantics Перевод: Zloy Kak Pё$

#024 – Знакомство с wpf/e

Не так давно произошел долгожданный релиз набора библиотек Microsoft .NET 3.0 и, возможно, появилась возможность вникнуть более подробно в привнесенные этим набором новшества. Возможно, но не тут- то было. Microsoft в серьез взялась за популяризацию Windows Presentation Foundation – и вот, с пылу с жару, новый (или не совсем новый) продукт WPF-E. E – это от английского “everywhere” – тобишь WPF везде. Отбросим мысли о том, что софтверный гигант решил таким образом всего лишь задавить (или все-таки слегка потеснить?) Flash и подумаем о том, что же означает это «везде». А означает это следующее – разработчики веб-сайтов смогут не только создавать стандартные, «тяжелые» XBAP-приложения (для работы с которыми уж очень нужен IE…) но и «легкие», основанные на XAML страницы. И при чем тут «везде»? А при том, что вместе с технологией WPF-E, компания выпустила несколько плагинов (объемом всего-то в один мегабайт), при помощи которых просмотр WPF-E контента в IE, Firefox и даже на компьютерах Apple Macintosh и даже на мобильных устройствах яйца выеденного стоить не будет. Поистине сильно желание Microsoft сразиться с Flash и, надо заметить, некоторые энтузиасты уже сделали абсолютно идентичные проекты на Flash и WPF-E и последний ничуть не уступает первому. Мало того, есть масса способов объединить обе технологии в рамках одного web-сайта, и не только объединить, но даже заставить взаимодействовать. Действительно, огромное поле для творчества. Итак, давайте создадим очень простую страницу типа «Hello World», чтобы познакомиться с технологией WPF/E. Что нам необходимо? Прежде всего скачать Silverlight. Во вторых, нам понадобится пустая html-страница, например, с таким содержанием:

Код:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>A Sample HTML page</title> </head> <body> </body> </html>

И в третьих, нам потребуется текстовый редактор, например «Блокнот» прекрасно подойдет. После того, как вы подготовили все вышеуказанные средства, Вам понадобится небольшой файл, основанный на JavaScript, который Microsoft любезно подготовила для разработчиков, с целью организовать очень быстрый и простой способ внедрить WPF-E контент на любую html-страницу. Скачайте архив с этим файлом тут: http://www.thevista.ru/datas/users/2180-aghost.zip , распакуйте архив и разместите вышеупомянутый файл, который имеет имя «aghost.js» в директории, в которой вы подготовили свою html-страницу. Теперь, нам необходимо подключить этот файл к нашей странице, для этого откройте Вашу страницу в блокноте и внесите следующую строку в секцию <head> вашего html-файла:

Код:

<script type="text/javascript" src="aghost.js"></script>

В моем случае код страницы будет выглядеть так:

Код:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>A Sample HTML page</title> <script type="text/javascript" src="aghost.js"></script> </head> <body> </body> </html>

Теперь нам необходимо создать область в которой будет работать наш WPF-E элемент. Это очень просто. Добавьте этот код внутрь секции <body> Вашего html-файла:

Код:

<!—Здесь будет работать WPF/E ActiveX контрол--> <div id="agControl1Host"> </div>

Создав таким образом область для работы контрола, необходимо описать этот самый контрол – сделать это, так же, довольно просто. Нижеизложенный код необходимо добавить внутрь блока <body>, но ниже вышеописанных тегов <div></div>:

Код:

<script type="text/javascript"> // Создаем WPF/E ActiveX контрол. // Используя данный метод мы избавляем пользователя от необходимости кликать по // ActiveX контролу прежде чем WPF/E получит информацию от пользователя new agHost( "agControl1Host", // hostElementID ( элемент HTML element который мы описали выше в теге <div>) "agControl1", // ID контрола WPF/E ActiveX которого мы создаем "300px", // ширина (width) "300px", // высота (height) "#D6D6D6", // цвет фона (backgroundcolor) null, // SourceElement (имя script-тэга содержащего xaml) "SampleProject.xaml", // файл источник контента (source file) "false", // Без окна (IsWindowless) "30", // Скорость кадров (MaxFrameRate) null // OnError handler (метод отлова ошибок) ); // также создаем глобальную переменную для WPF/E ActiveX контрола, // которую мы можем использовать, чтобы найти xaml элементы var agControl = document.getElementById("agControl1"); </script>

Итак, возможно Вам покажется, что данный код несколько громоздкий, но на самом деле он не содержит ни одной лишней строки. Вы уже поняли, что мы применяем комбинированный HTML+Sсript язык, для описания. Думаю, разобраться в нем не составит проблемы. Тем не менее, внимательно изучите комментарии, которые я внес в код, для Вас. Эти комментарии помогут Вам максимально быстро разобраться с тем, как правильно определить отображающий элемент (под отображающим элементом я понимаю ту область, которая будет отображать WPF-E контент). Итак, внимательный читатель обратил внимание на параметр «Source File» - и правильно, так как именно этот параметр ссылается на xaml-файл, в данном случае с именем «SampleProject.xaml», который и содержит замечательный WPF-контент. Чтож, создайте пустой xaml-файл (для этого достаточно создать текстовый документ и изменить расширение с «txt» на «xaml») c нужным именем и разместите его в директории, в которой находится ваша html-страница. Вы уже знакомы с тем, какие элементы используются для рисования в XAML. Все, что нужно добавить, это то, что контент WPF-E всегда размещается внутри контейнера <Canvas>, в другом все идентично. Для того, чтобы закончить нашу страницу нарисуем кое-что в нашем xaml-файле. Внесите в него такой код:

Код:

<Canvas Width="300" Height="300" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Ellipse Height="200" Width="200" Canvas.Left="30" Canvas.Top="30" Stroke="Black" StrokeThickness="10" Fill="LightBlue"/> </Canvas>

Сохраните все документы и запустите Вашу страницу: Поздравляю! Вы только что создали свою первую страницу на базе WPF-E. Что еще можно добавить? Если Вы хотите разместить на странице несколько независимых контролов для отображения XAML – не забудьте присвоить каждому из них уникальное имя. Что? Вы не видите содержимого данной страницы? Это может быть только потому, что вы забыли установить плагин для Вашего броузера.

Соседние файлы в папке !