<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Russian Coding 4 Fun</title><subtitle type="html" /><id>http://blogs.msdn.com/b/rucoding4fun/atom.aspx</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/rucoding4fun/" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/b/rucoding4fun/atom.aspx" /><generator uri="http://telligent.com" version="5.6.50428.7875">Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><updated>2013-02-27T11:44:46Z</updated><entry><title>Тук, тук… Создание дверного сигнализатора на Arduino</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/rucoding4fun/archive/2013/05/20/knock-knock-building-an-arduino-door-entry-alarm.aspx" /><id>http://blogs.msdn.com/b/rucoding4fun/archive/2013/05/20/knock-knock-building-an-arduino-door-entry-alarm.aspx</id><published>2013-05-20T19:10:52Z</published><updated>2013-05-20T19:10:52Z</updated><content type="html">&lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://channel9.msdn.com/Niners/gduncan411"&gt;Грэг Дункан&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Настало время небольшого аппаратного хака (в хорошем смысле). Не просто вставь и работай, мы поговорим о макетных платах, проводах, Arduino и немного о кодировании.&lt;/p&gt;  &lt;p&gt;Ну, может быть это не крутой хакинг (совсем), но для не электронных парней, вроде меня, это так … &lt;img title="clip_image002" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image002" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/1731.clip_5F00_image002_5F00_65F9DFE9.png" width="28" height="31" /&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;&lt;a href="http://blogs.msdn.com/b/abhinaba/archive/2013/04/30/arduino-fun-door-entry-alarm.aspx"&gt;Развлечение с Arduino – дверной сигнализатор&lt;/a&gt;&lt;/h4&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Physical_computing"&gt;Физические вычисления&lt;/a&gt; и «интернет вещей» – сверхзахватывающие области, развивающиеся прямо сейчас. Даже десятки лет назад можно было подключать датчики, удаленно получать данные от них и обрабатывать их. Чем отличается наше время? Тем, что мощный микроконтроллер неприлично дешев и у большинства из нас в кармане находится действительно мощное вычислительное устройство. Также сегодня не составляет труда беспроводные соединения и почти в каждом доме есть беспроводная сеть.&lt;/p&gt;    &lt;p&gt;Все вместе позволяет создавать действительно неотразимые и замечательные решения, где данные путешествуют от датчиков по беспроводным сетям в облако и затем в мобильный телефон, который мы носим с собой. В конечном итоге, я хотел создать умную дверь, чтобы, находясь на работе, получать оповещение, когда кто-то стучится в дверь нашего дома. Может быть, я смогу удаленно открыть дверь. Возможности бесконечны, но время ограничено, поэтому давайте посмотрим, чего я смогу достичь за разумное время.&lt;/p&gt;    &lt;p&gt;...&lt;/p&gt;    &lt;h6&gt;Проект&lt;/h6&gt;    &lt;p&gt;&lt;img title="clip_image004" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image004" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/1373.clip_5F00_image004_5F00_12A299C3.png" width="309" height="275" /&gt;&lt;/p&gt;    &lt;p&gt;Я решил начать с создания простой сигнализации и узнать, сколько времени понадобиться на ее сборку. В колледже я делал нечто похожее, но без микропроцессора (на основе 555 микросхемы и инфракрасного фототранзистора) приличное время заняло соединение всех компонентов. Основная идея состоит в том, что на одной стороне двери будет располагаться источник света, а с другой – сенсор. Когда кто-то встает на линию между источником света и сенсором, последний преграждается и генерируется сигнал тревоги. &lt;/p&gt;    &lt;p&gt;Когда я собирал такую схему в колледже, я сделал ее надежной, используя пульсирующий (с фиксированной частотой) инфракрасный светодиод и инфракрасный сенсор. В текущем проекте я применил видимый свет и фоторезистор, который входил в набор.&lt;/p&gt;    &lt;p&gt;&lt;img title="clip_image006" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image006" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/5483.clip_5F00_image006_5F00_22CE61BC.png" width="346" height="459" /&gt;&lt;/p&gt;    &lt;p&gt;...&lt;/p&gt;    &lt;p&gt;&lt;img title="clip_image008" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image008" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/6472.clip_5F00_image008_5F00_3FE3E3F9.png" width="587" height="782" /&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/16e_VQopQRc&amp;amp;hl=en"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/16e_VQopQRc&amp;amp;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;  &lt;p&gt;Теперь, за работу!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10420110" width="1" height="1"&gt;</content><author><name>Russian MSDN</name><uri>http://blogs.msdn.com/Russian-MSDN/ProfileUrlRedirect.ashx</uri></author><category term="Arduino" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/Arduino/" /></entry><entry><title>Средство динамической смены экранов блокировки для Windows Phone 8, созданное с помощью ASP.NET MVC и Azure Mobile Services</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/rucoding4fun/archive/2013/05/16/dynamic-lockscreen-changer-for-windows-phone-8-built-with-asp-net-mvc-and-azure-mobile-services.aspx" /><id>http://blogs.msdn.com/b/rucoding4fun/archive/2013/05/16/dynamic-lockscreen-changer-for-windows-phone-8-built-with-asp-net-mvc-and-azure-mobile-services.aspx</id><published>2013-05-16T12:22:29Z</published><updated>2013-05-16T12:22:29Z</updated><content type="html">&lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://channel9.msdn.com/Niners/Clint"&gt;Клинт Руткас (Clint Rutkas)&lt;/a&gt;, &lt;a href="http://channel9.msdn.com/Niners/DennisDel"&gt;Ден Делимарски (Den Delimarsky)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;С выпуском Windows Phone 8 стало доступно &lt;a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206968%28v=vs.105%29.aspx"&gt;несколько API для разработчиков&lt;/a&gt;, позволяющих сторонним приложениям менять изображение экрана блокировки на устройстве. В этой статье формируется инфраструктура и создается мобильное приложение, которое поддерживает динамический набор, из которого можно выбирать изображения, а затем циклически менять их как фоновые для экрана блокировки.&lt;/p&gt;  &lt;h5&gt;Что вам понадобится&lt;/h5&gt;  &lt;p&gt;Вам нужно будет скачать и установить &lt;a href="http://www.asp.net/mvc/mvc3"&gt;ASP.NET MVC3&lt;/a&gt; для работы с клиентским веб-интерфейсом и &lt;a href="http://dev.windowsphone.com/en-us/downloadsdk"&gt;Windows Phone 8 SDK&lt;/a&gt; для разработки мобильных приложений. Обязательно создайте учетную запись &lt;a href="http://www.windowsazure.com/en-us/develop/mobile/"&gt;Azure Mobile Services&lt;/a&gt; и, конечно же, не забудьте скачать и установить &lt;a href="http://www.windowsazure.com/en-us/develop/mobile/developer-tools/"&gt;клиентские библиотеки Azure Mobile Services&lt;/a&gt;. Все три компонента предоставляются совершенно бесплатно.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Примечание:&lt;/b&gt; &lt;i&gt;если на компьютере разработчика не установлен &lt;/i&gt;&lt;i&gt;Azure&lt;/i&gt;&lt;i&gt; &lt;/i&gt;&lt;i&gt;Mobile&lt;/i&gt;&lt;i&gt; &lt;/i&gt;&lt;i&gt;Services&lt;/i&gt;&lt;i&gt; &lt;/i&gt;&lt;i&gt;SDK&lt;/i&gt;&lt;i&gt;, процесс компиляции приложения для &lt;/i&gt;&lt;i&gt;Windows&lt;/i&gt;&lt;i&gt; &lt;/i&gt;&lt;i&gt;Phone&lt;/i&gt;&lt;i&gt; &lt;/i&gt;&lt;i&gt;завершится неудачей.&lt;/i&gt;&lt;/p&gt;  &lt;h5&gt;Подготовка хранилища данных&lt;/h5&gt;  &lt;p&gt;Сначала мы должны определиться с общей архитектурой приложения и организовать рабочий процесс. Приложение будет поддерживать два способа назначения динамического экрана блокировки:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;с помощью собственных наборов изображений, предоставляемых сервисом; &lt;/li&gt;    &lt;li&gt;посредством наборов, создаваемых на основе изображений, которые предоставляются сервисом, но управляются конечным пользователем. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Давайте поговорим о модели данных в целом. Каждое изображение относится к определенной категории, и, чтобы отслеживать каждое из них, нам нужна таблица с двумя полями: идентификатором и названием категории. Нам также требуется другая базовая таблица, содержащая ссылки на сами изображения, со следующими полями: URL изображения, описательным названием и идентификатором той категории, к которой оно относится. Общая структура выглядит так:&lt;/p&gt;  &lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/0003.image_5F00_02DE6733.png" width="325" height="145" /&gt;&lt;/p&gt;  &lt;p&gt;Теперь перейдем на портал управления Windows Azure и создадим новый мобильный сервис.&lt;/p&gt;  &lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/6574.image_5F00_0DBB487B.png" width="564" height="391" /&gt;&lt;/p&gt;  &lt;p&gt;Теперь вы должны указать информацию о базе данных — точно так же, как это делается для стандартной базы данных SQL Server:&lt;/p&gt;  &lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/7534.image_5F00_2AE0F085.png" width="568" height="372" /&gt;&lt;/p&gt;  &lt;p&gt;При создании базу данных можно легко интегрировать с SQL Server Management Studio. Вам понадобится адрес сервера, который можно получить на портале управления Windows Azure. Для входа используйте удостоверения, указанные вами при создании основной базы данных.&lt;/p&gt;  &lt;p&gt;Создайте две упомянутые ранее таблицы со следующей конфигурацией полей:&lt;/p&gt;  &lt;p&gt;&lt;b&gt;• Categories&lt;/b&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;ID – &lt;b&gt;int&lt;/b&gt; &lt;/li&gt;    &lt;li&gt;Name – &lt;b&gt;varchar(100)&lt;/b&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;b&gt;• Images&lt;/b&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;ID – &lt;b&gt;int&lt;/b&gt; &lt;/li&gt;    &lt;li&gt;URL – &lt;b&gt;varchar(500)&lt;/b&gt; &lt;/li&gt;    &lt;li&gt;Name – &lt;b&gt;varchar(100)&lt;/b&gt; &lt;/li&gt;    &lt;li&gt;CategoryID – &lt;b&gt;int&lt;/b&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Вы мо��ете создать эти таблицы либо в SQL Server Management Studio, либо через портал управления Windows Azure. Однако вам потребуется Management Studio, чтобы создать структуру полей, так как портал управления Windows Azure на данный момент не поддерживает необходимую для этого функциональность.&lt;/p&gt;  &lt;p&gt;По умолчанию поле &lt;b&gt;id&lt;/b&gt; будет создано автоматически. Чтобы добавить поле Name в таблицу Categories, выполните этот запрос: &lt;/p&gt;  &lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;   &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;ALTER&lt;/span&gt; &lt;span style="color: #0000ff"&gt;TABLE&lt;/span&gt; c4flockscreen.Categories&lt;br /&gt;&lt;span style="color: #0000ff"&gt;ADD&lt;/span&gt; Name &lt;span style="color: #0000ff"&gt;VARCHAR&lt;/span&gt;(100)&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;

&lt;p&gt;Чтобы добавить недостающие поля в таблицу Images, просто выполните следующий запрос:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;ALTER&lt;/span&gt; &lt;span style="color: #0000ff"&gt;TABLE&lt;/span&gt; c4flockscreen.Images&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;ADD&lt;/span&gt; URL &lt;span style="color: #0000ff"&gt;VARCHAR&lt;/span&gt;(500),&lt;br /&gt;&lt;br /&gt;Name &lt;span style="color: #0000ff"&gt;VARCHAR&lt;/span&gt;(100),&lt;br /&gt;&lt;br /&gt;CategoryID &lt;span style="color: #0000ff"&gt;INT&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;

&lt;p&gt;Теперь, когда база данных готова, мы перейдем к работе над веб-уровнем, который, в конечном счете, станет административным порталом для сервиса.&lt;/p&gt;

&lt;h5&gt;Создание веб-портала&lt;/h5&gt;

&lt;p&gt;Должен быть какой-то простой способ управления изображениями и постоянного расширения набора возможными обоями (фоновыми изображениями) экрана блокировки. Один из способов сделать это — создать портал управления, способный выполнять базовые CRUD-операции.&lt;/p&gt;

&lt;p&gt;Начнем с создания пустого проекта:&lt;/p&gt;

&lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/6837.image_5F00_609635DF.png" width="325" height="295" /&gt;&lt;/p&gt;

&lt;p&gt;Если вы еще не знакомы с шаблоном Model-View-Controller (MVC), &lt;a href="http://msdn.microsoft.com/en-us/library/ff649643.aspx"&gt;здесь есть хорошая статья&lt;/a&gt;, поясняющая его основы.&lt;/p&gt;

&lt;p&gt;Создайте новый контроллер в папке &lt;b&gt;Controllers&lt;/b&gt;, присвойте ему имя &lt;b&gt;HomeController&lt;/b&gt;. Это будет единственный контроллер в данном проекте. Пока добавьте функцию на основе &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.actionresult%28v=vs.108%29.aspx"&gt;ActionResult&lt;/a&gt;, которая будет возвращать основное представление:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.Mvc;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; Coding4Fun.Lockscreen.Web.Controllers&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult MainView() &lt;br /&gt;&lt;br /&gt;     { &lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(); &lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;

&lt;p&gt;Контроллер без соответствующих представлений бесполезен, поэтому создайте новое представление в &lt;b&gt;Views&lt;/b&gt;&lt;b&gt;/&lt;/b&gt;&lt;b&gt;Home&lt;/b&gt; и присвойте ему имя &lt;b&gt;MainView&lt;/b&gt;. На данный момент не заморачивайтесь визуальной структурой страницы, а уделите внимание функциональному аспекту клиентского веб-интерфейса. Если вы сейчас запустите приложение, то, скорее всего, получите ответ с кодом 404. Это означает, что связанное начальное представление по умолчанию не найдено. Откройте &lt;b&gt;App&lt;/b&gt;&lt;b&gt;_&lt;/b&gt;&lt;b&gt;Start&lt;/b&gt;&lt;b&gt;/&lt;/b&gt;&lt;b&gt;RouteConfig&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;cs&lt;/b&gt; и убедитесь, что представлением по умолчанию является &lt;b&gt;MainView&lt;/b&gt;, а не &lt;b&gt;Index&lt;/b&gt;.&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;routes.MapRoute(&lt;br /&gt;&lt;br /&gt;name: &lt;span style="color: #006080"&gt;&amp;quot;Default&amp;quot;&lt;/span&gt;,&lt;br /&gt;&lt;br /&gt;url: &lt;span style="color: #006080"&gt;&amp;quot;{controller}/{action}/{id}&amp;quot;&lt;/span&gt;,&lt;br /&gt;&lt;br /&gt;defaults: &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; { controller = &lt;span style="color: #006080"&gt;&amp;quot;Home&amp;quot;&lt;/span&gt;, action = &lt;span style="color: #006080"&gt;&amp;quot;MainView&amp;quot;&lt;/span&gt;, id = UrlParameter.Optional }&lt;br /&gt;&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;

&lt;p&gt;Базовая часть создана, и теперь, если запустить веб-приложение, вы увидите пока что пустую HTML-страницу:&lt;/p&gt;

&lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/1856.image_5F00_3DF1F764.png" width="512" height="349" /&gt;&lt;/p&gt;

&lt;p&gt;Теперь нам нужно обрабатывать данные, получаемые из базы данных Azure Mobile Services. ASP.NET SDK нет, но к этой базе данных можно легко &lt;a href="http://msdn.microsoft.com/en-us/library/windowsazure/jj710108.aspx"&gt;обращаться через REST API&lt;/a&gt;. Однако перед этим мы должны определить модели данных для таблиц Categories и Images. Начнем с создания двух классов в папке Models:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Category&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;cs&lt;/b&gt;&lt;b&gt;:&lt;/b&gt;&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Category&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;? id { get; set; }&lt;br /&gt;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Image.cs:&lt;/b&gt; &lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Image&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;? id { get; set; } &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; URL { get; set; }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CategoryID { get; set; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Каждое из свойств связывается с соответствующим полем в ранее созданной базе данных. Заметьте, что ID может принимать null-значения. Это введено потому, что по умолчанию индекс будет назначаться автоматически. Когда создается новый экземпляр Category или Image, я не задаю свойство &lt;b&gt;id&lt;/b&gt; явным образом, поэтому хранение в нем null вместо потенциально возможного нулевого значения по умолчанию гарантирует, что оно будет должным образом установлено на серверной стороне.&lt;/p&gt;

&lt;p&gt;Теперь создадим механизм подключений, который позволит нам запрашивать содержимое хранилища данных. Для этого я создал папку &lt;b&gt;DataStore&lt;/b&gt;, а в ней — класс &lt;b&gt;DataEngine&lt;/b&gt;. Нам понадобится уникальный ключ API для каждого запроса, поэтому откройте портал управления Windows Azure и получите его оттуда:&lt;/p&gt;

&lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/8863.image_5F00_226CF561.png" width="688" height="308" /&gt;&lt;/p&gt;

&lt;p&gt;Чтобы сохранить согласованность между проектами и получить возможность повторного использования одних и тех же значений ключа Azure Mobile Services API и базового URL, я создал класс &lt;b&gt;AuthConstants&lt;/b&gt; в контексте проекта &lt;b&gt;Coding&lt;/b&gt;&lt;b&gt;4&lt;/b&gt;&lt;b&gt;Fun&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Lockscreen&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Core&lt;/b&gt;. В нем имеются три статических поля:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; AuthConstants&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; AmsApiKey = &lt;span style="color: #006080"&gt;&amp;quot;YOUR_KEY_HERE&amp;quot;&lt;/span&gt;; &lt;br /&gt;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; AmsUrl = &lt;span style="color: #006080"&gt;&amp;quot;https://c4flockscreen.azure-mobile.net/&amp;quot;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; AmsTableUrl = AmsUrl + &lt;span style="color: #006080"&gt;&amp;quot;tables/&amp;quot;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;В проекте ASP.NET операции запроса выполняются с помощью &lt;a href="http://msdn.microsoft.com/en-us/library/system.net.http.httpclient.aspx"&gt;HttpClient&lt;/a&gt;, инициализируемого в конструкторе класса; этот запрос также содержит ключ, используемый для аутентификации запросов через заголовок X-ZUMO-APPLICATION:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; HttpClient client;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; DataEngine()&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;   client = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HttpClient(); &lt;br /&gt;&lt;br /&gt;   client.DefaultRequestHeaders.Add(&lt;span style="color: #006080"&gt;&amp;quot;X-ZUMO-APPLICATION&amp;quot;&lt;/span&gt;, KEY);&lt;br /&gt;&lt;br /&gt;   client.DefaultRequestHeaders.Accept.Add(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MediaTypeWithQualityHeaderValue(&lt;span style="color: #006080"&gt;&amp;quot;application/json&amp;quot;&lt;/span&gt;)); &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Это основной каркас поддержки работы с данными. Я также реализовал два базовых метода, чтобы получать все существующие категории:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IEnumerable&amp;lt;Category&amp;gt; GetAllCategories()&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;  var result = client.GetStringAsync(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Concat(CORE_URL,&lt;span style="color: #006080"&gt;&amp;quot;Categories&amp;quot;&lt;/span&gt;)).Result;&lt;br /&gt;&lt;br /&gt;  IEnumerable&amp;lt;Category&amp;gt; categories = JsonConvert.DeserializeObject&amp;lt;IEnumerable&amp;lt;Category&amp;gt;&amp;gt;(result);&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; categories; &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;и изображения:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IEnumerable&amp;lt;Image&amp;gt; GetAllImages()&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;  var result = client.GetStringAsync(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Concat(CORE_URL, &lt;span style="color: #006080"&gt;&amp;quot;Images&amp;quot;&lt;/span&gt;)).Result;&lt;br /&gt;&lt;br /&gt;  IEnumerable&amp;lt;Image&amp;gt; images = JsonConvert.DeserializeObject&amp;lt;IEnumerable&amp;lt;Image&amp;gt;&amp;gt;(result);&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; images; &lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Для каждого из этих методов базовый запрос выдается с именем таблицы, за которым следует базовый URL (представленный константой &lt;b&gt;CORE&lt;/b&gt;&lt;b&gt;_&lt;/b&gt;&lt;b&gt;URL&lt;/b&gt;). Так как &lt;a href="http://www.hanselman.com/blog/VisualStudio2012RCIsReleasedTheBigWebRollup.aspx"&gt;JSON.NET теперь включен в ASP.NET&lt;/a&gt;, я могу легко десериализовать возвращаемый массив JSON-данных в &lt;b&gt;IEnumerable&lt;/b&gt;&lt;b&gt;&amp;lt;&lt;/b&gt;&lt;b&gt;Type&lt;/b&gt;&lt;b&gt;&amp;gt;&lt;/b&gt;. Однако в подходе &lt;b&gt;GetAllImages&lt;/b&gt; есть одна проблема. Он подразумевает, что, даже если я хочу использовать LINQ для запроса существующего набора изображений, я должен сначала локально загрузить весь набор.&lt;/p&gt;

&lt;p&gt;К счастью, Azure Mobile Services REST API предоставляет конечную точку с фильтрацией, и именно ее я использую в &lt;b&gt;GetCategoryById&lt;/b&gt; и &lt;b&gt;GetImagesByCategoryId&lt;/b&gt;:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Category GetCategoryById(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; id)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; composite = &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Concat(CORE_URL, &lt;span style="color: #006080"&gt;&amp;quot;Categories?$filter=(id%20eq%20&amp;quot;&lt;/span&gt;, id.ToString(), &lt;span style="color: #006080"&gt;&amp;quot;)&amp;quot;&lt;/span&gt;); &lt;br /&gt;&lt;br /&gt;  var result = client.GetStringAsync(composite).Result;&lt;br /&gt;&lt;br /&gt;  IEnumerable&amp;lt;Category&amp;gt; categories = JsonConvert.DeserializeObject&amp;lt;IEnumerable&amp;lt;Category&amp;gt;&amp;gt;(result);&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; categories.FirstOrDefault();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IEnumerable&amp;lt;Image&amp;gt; GetImagesByCategoryId(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; id)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; composite = &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Concat(CORE_URL, &lt;span style="color: #006080"&gt;&amp;quot;Images?$filter=(CategoryID%20eq%20&amp;quot;&lt;/span&gt;, id.ToString(), &lt;span style="color: #006080"&gt;&amp;quot;)&amp;quot;&lt;/span&gt;); &lt;br /&gt;&lt;br /&gt;  var result = client.GetStringAsync(composite).Result;&lt;br /&gt;&lt;br /&gt;  IEnumerable&amp;lt;Image&amp;gt; images = JsonConvert.DeserializeObject&amp;lt;IEnumerable&amp;lt;Image&amp;gt;&amp;gt;(result);&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; images();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Обратите внимание на параметр &lt;b&gt;?$&lt;/b&gt;&lt;b&gt;filter&lt;/b&gt;&lt;b&gt;=&lt;/b&gt;, в котором условным выражением является закодированный URL, а все его содержимое заключено в скобки. В запросе категории я проверяю значение &lt;b&gt;id&lt;/b&gt;, а в запросе изображения — &lt;b&gt;CategoryID&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;В папке &lt;b&gt;Views&lt;/b&gt;&lt;b&gt;/&lt;/b&gt;&lt;b&gt;Home&lt;/b&gt; создайте новое представление и присвойте ему имя Images. Оно будет использоваться для перечисления существующих изображений, связанных с одной из выбранных категорий. Вы также должны модифицировать код контроллера для обработки входящих данных:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; Coding4Fun.Lockscreen.Web.DataStore;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.Mvc;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; Coding4Fun.Lockscreen.Web.Controllers&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;     DataEngine engine; &lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; HomeController()&lt;br /&gt;&lt;br /&gt;     { &lt;br /&gt;&lt;br /&gt;        engine = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DataEngine(); &lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult MainView()&lt;br /&gt;&lt;br /&gt;     { &lt;br /&gt;&lt;br /&gt;        var categories = engine.GetAllCategories(); &lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(categories);&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Images(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; categoryId)&lt;br /&gt;&lt;br /&gt;     { &lt;br /&gt;&lt;br /&gt;        var images = engine.GetImagesByCategoryId(categoryId); &lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (images != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;        { &lt;br /&gt;&lt;br /&gt;           &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(images); &lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(&lt;span style="color: #006080"&gt;&amp;quot;MainView&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;

&lt;p&gt;Для основного представления я получаю список категорий и передаю их как связанную модель. Для представления Images идентификатор категории передается как аргумент, который впоследствии позволит механизму возвращать список всех изображений, чей &lt;b&gt;CategoryID&lt;/b&gt; имеет это значение. Если возвращаемый список не равен null, это представление появляется на экране. В ином случае основное представление является конечной точкой.&lt;/p&gt;

&lt;p&gt;В текущем состоянии этот клиентский интерфейс можно будет использовать для перечисления существующих категорий, но для добавления, удаления или обновления элементов. Добавление категории и изображения требует модификации запроса &lt;b&gt;HttpClient&lt;/b&gt; с помощью &lt;a href="http://msdn.microsoft.com/en-us/library/system.net.http.httprequestmessage.aspx"&gt;HttpRequestMessage&lt;/a&gt;. Например, вот как можно добавить категорию через мой класс DataEngine:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; HttpStatusCode AddCategory(Category category)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;   var serializedObject = JsonConvert.SerializeObject(category, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });&lt;br /&gt;&lt;br /&gt;   var request = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HttpRequestMessage(HttpMethod.Post, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Concat(CORE_URL, &lt;span style="color: #006080"&gt;&amp;quot;Categories&amp;quot;&lt;/span&gt;));&lt;br /&gt;&lt;br /&gt;   request.Content = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StringContent(serializedObject, Encoding.UTF8, &lt;span style="color: #006080"&gt;&amp;quot;application/json&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;   var response = client.SendAsync(request).Result;&lt;br /&gt;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; response.StatusCode;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Чтобы сериализовать объект, подлежащий вставке, используются возможности JSON.NET. Запрос POST выполняется применительно к таблице стандартных URL с JSON-строкой, закодированной в UTF8. Так как клиент уже имеет заголовок базовой аутентификации, достаточно вызвать функцию &lt;a href="http://msdn.microsoft.com/en-us/library/hh138176.aspx"&gt;SendAsync&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;При обновлении категории применяется тот же подход, но для запроса используется &lt;a href="http://tools.ietf.org/html/rfc5789"&gt;метод PATCH&lt;/a&gt;, и URL содержит индекс категории, которую требуется обновить:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; HttpStatusCode UpdateCategory(Category category)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;   var request = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HttpRequestMessage(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HttpMethod(&lt;span style="color: #006080"&gt;&amp;quot;PATCH&amp;quot;&lt;/span&gt;), &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Concat(CORE_URL, &lt;span style="color: #006080"&gt;&amp;quot;Categories&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;, category.id)); &lt;br /&gt;&lt;br /&gt;   var serializedObject = JsonConvert.SerializeObject(category);&lt;br /&gt;&lt;br /&gt;   request.Content = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StringContent(serializedObject, Encoding.UTF8, &lt;span style="color: #006080"&gt;&amp;quot;application/json&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;   var response = client.SendAsync(request).Result;&lt;br /&gt;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; response.StatusCode;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Чтобы удалить какую-либо категорию из хранилища данных, нужно просто передать ему параметр, указывающий индекс удаляемой категории:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; HttpStatusCode DeleteCategoryFromId(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; categoryId)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;   var request = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HttpRequestMessage(HttpMethod.Delete, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Concat(CORE_URL, &lt;span style="color: #006080"&gt;&amp;quot;Categories&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;, categoryId)); &lt;br /&gt;&lt;br /&gt;   var response = client.SendAsync(request).Result;&lt;br /&gt;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; response.StatusCode;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;В случае изображений можно использовать те же методы, передавая таблицу &lt;b&gt;Images&lt;/b&gt; как имя цели в составном URL. Теперь вернемся к работе над некоторыми из представлений. Статический список категорий совсем не интересен, поэтому давайте создадим способ добавления новых категорий. Щелкните правой кнопкой мыши папку &lt;b&gt;Views&lt;/b&gt;&lt;b&gt;/&lt;/b&gt;&lt;b&gt;Home&lt;/b&gt; и выберите &lt;b&gt;Add&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;View&lt;/b&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/0825.image_5F00_7EF050FB.png" width="321" height="317" /&gt;&lt;/p&gt;

&lt;p&gt;Очень удобно, что в Visual Studio можно задействовать базовый шаблон Scaffold при создании строго типизированного представления. В этом случае я сопоставляю его с классом &lt;b&gt;Category&lt;/b&gt; и использую шаблон &lt;b&gt;Create&lt;/b&gt;. Теперь мне нужно модифицировать код контроллера для обработки запросов к AddCategory. Я должен обрабатывать два типа запросов (GET и POST), поскольку это представление будет отображаться как при добавлении, так и при передаче элемента:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult AddCategory()&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(); &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[HttpPost]&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult AddCategory(Category category)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (ModelState.IsValid) &lt;br /&gt;&lt;br /&gt;   { &lt;br /&gt;&lt;br /&gt;      engine.AddCategory(category); &lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; RedirectToAction(&lt;span style="color: #006080"&gt;&amp;quot;MainView&amp;quot;&lt;/span&gt;); &lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;

&lt;p&gt;Для запроса GET я просто возвращаю представление, а для запроса POST я добавляю категорию, которая была определена связанной моделью через локальный экземпляр &lt;b&gt;DataEngine&lt;/b&gt;, после чего пользователь перенаправляется в основное представление. Но нам также нужно добавить ActionResult для MainView, чтобы получить список элементов, которые содержатся в данный момент в таблице Categories:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult MainView()&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;   var categories = engine.GetAllCategories(); &lt;br /&gt;&lt;br /&gt;   &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(categories);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Экземпляр &lt;b&gt;DataEngine&lt;/b&gt; будет возвращать все категории в форме &lt;b&gt;IEnumerable&lt;/b&gt;&lt;b&gt;&amp;lt;&lt;/b&gt;&lt;b&gt;Category&lt;/b&gt;&lt;b&gt;&amp;gt;&lt;/b&gt;; они передаваются в качестве модели для основного представления. Разметка MainView.cshtml может быть столь же простой, как таблица:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;@{ &lt;br /&gt;&lt;br /&gt;ViewBag.Title = &amp;quot;Coding4Fun Dynamic Lockscreen&amp;quot;; &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;h2&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Coding4Fun Dynamic Lockscreen - Categories&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;h2&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;table&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;tr&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;b&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;ID&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;b&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;b&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Category Name&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;b&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;tr&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;@foreach (var p in Model)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;tr&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;@p.id&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;@p.Name&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;@Html.ActionLink(&amp;quot;Images&amp;quot;, &amp;quot;Images&amp;quot;, new { categoryId = p.id })&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;@Html.ActionLink(&amp;quot;Edit&amp;quot;, &amp;quot;EditCategory&amp;quot;, new { categoryId = p.id })&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;@Html.ActionLink(&amp;quot;Delete&amp;quot;, &amp;quot;DeleteCategory&amp;quot;, new { categoryId = p.id })&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;tr&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;table&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;@Html.ActionLink(&amp;quot;Add Category&amp;quot;, &amp;quot;AddCategory&amp;quot;)&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Вспомогательный метод &lt;b&gt;ActionLink&lt;/b&gt; позволяет обращаться к представлению и при необходимости передавать ему специфические параметры (например, когда мне нужно идентифицировать категорию, подлежащую удалению или редактированию). Некоторые из перечисленных здесь представлений пока не созданы, но в любом случае можно легко использовать подстановочные имена (placeholder names).&lt;/p&gt;

&lt;p&gt;В итоге основная страница будет выглядеть так:&lt;/p&gt;

&lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/5315.image_5F00_3511C94B.png" width="614" height="404" /&gt;&lt;/p&gt;

&lt;p&gt;Заметьте, что теперь новые категории можно добавлять и щелчком ссылки Add Category внизу страницы. Это действие перенаправит вас в созданное представление &lt;b&gt;AddCategory&lt;/b&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/0167.image_5F00_211836B5.png" width="614" height="404" /&gt;&lt;/p&gt;

&lt;p&gt;Рассмотрим, как реализовать редактирование категорий в клиентском веб-интерфейсе. Прежде всего, создайте новое представление в &lt;b&gt;Views&lt;/b&gt;&lt;b&gt;/&lt;/b&gt;&lt;b&gt;Home&lt;/b&gt; и присвойте ему имя &lt;b&gt;EditCategory&lt;/b&gt;. Используйте Scaffold-шаблон &lt;b&gt;Edit&lt;/b&gt;. Как и &lt;b&gt;AddCategory&lt;/b&gt;, &lt;b&gt;EditCategory&lt;/b&gt; нужно обрабатывать в контроллере разными способами для запросов GET и POST:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult EditCategory(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; categoryId)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  Category category; &lt;br /&gt;&lt;br /&gt;  category = engine.GetCategoryById(categoryId);&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (category != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(category);&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(&lt;span style="color: #006080"&gt;&amp;quot;MainView&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[HttpPost]&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult EditCategory(Category category)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (ModelState.IsValid) &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    engine.UpdateCategory(category); &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; RedirectToAction(&lt;span style="color: #006080"&gt;&amp;quot;MainView&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;В случае запроса &lt;b&gt;GET&lt;/b&gt; мы должны идентифицировать категорию, которую нужно добавить по ее индексу, поэтому мы передаем аргумент &lt;b&gt;categoryId&lt;/b&gt; представлению, которое потом используется экземпляром &lt;b&gt;DataEngine&lt;/b&gt; для получения категории из хранилища данных. Для операции POST применяется приведенная выше реализация &lt;b&gt;UpdateCategory&lt;/b&gt;, где выполняется запрос PATCH с сериализованным объектом, связанным с данным представлением.&lt;/p&gt;

&lt;p&gt;Операция Delete не требует дополнительного представления, но контроллеру по-прежнему нужен обработчик, и мы используем такой фрагмент кода:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult DeleteCategory(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; categoryId)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  engine.DeleteCategoryFromId(categoryId); &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; RedirectToAction(&lt;span style="color: #006080"&gt;&amp;quot;MainView&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Тот же подход применим к добавлению, удалению и редактированию элементов в списке изображений. Однако для добавления изображений может понадобиться передача идентификатора категории. Когда изображения перечисляются после выбора категории, необходимо предоставить способ для идентификации категории, в которую должны быть добавлены новые сущности. Для этого при инициации действия Images можно передать индекс категории из основного контроллера в представление:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Images(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; categoryId)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  var images = engine.GetImagesByCategoryId(categoryId); &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (images != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    ViewData[&lt;span style="color: #006080"&gt;&amp;quot;CID&amp;quot;&lt;/span&gt;] = categoryId; &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(images);&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(&lt;span style="color: #006080"&gt;&amp;quot;MainView&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Впоследствии значение &lt;b&gt;categoryId&lt;/b&gt; можно получить по ключу &lt;b&gt;CID&lt;/b&gt; для &lt;b&gt;ViewData&lt;/b&gt; внутри самого представления.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Теперь обсудим, как изображения представляются для каждой категории. Я создал свое представление для перечисления всех изображений, связанных с категорией Images. Если вы посмотрите на приведенный выше код контроллера, то заметите, что я передаю идентификатор категории, используемый при выполнении запроса к набору изображений, а возвращаемый набор устанавливается как связанная модель&lt;/strong&gt;:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Images(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; categoryId)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  var images = engine.GetImagesByCategoryId(categoryId); &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (images != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;     ViewData[&lt;span style="color: #006080"&gt;&amp;quot;CID&amp;quot;&lt;/span&gt;] = categoryId; &lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(images);&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(&lt;span style="color: #006080"&gt;&amp;quot;MainView&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Если вам нужно добавить какое-то изображение, вызовите представление &lt;b&gt;AddImage&lt;/b&gt;. В &lt;b&gt;HomeController&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;cs&lt;/b&gt; содержатся реализации для запросов GET и POST:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult AddImage(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; categoryId)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  Image image = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Image(); &lt;br /&gt;&lt;br /&gt;  image.CategoryID = categoryId;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(image); &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[HttpPost]&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult AddImage(HttpPostedFileBase file, Image image)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (file != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; file.ContentLength &amp;gt; 0) &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    var fileName = Path.GetFileName(file.FileName); &lt;br /&gt;&lt;br /&gt;    var path = Path.Combine(Server.MapPath(&lt;span style="color: #006080"&gt;&amp;quot;~/Uploads&amp;quot;&lt;/span&gt;), image.CategoryID.ToString(), fileName);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; dirPath = Path.GetDirectoryName(path);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!Directory.Exists(dirPath))&lt;br /&gt;&lt;br /&gt;       Directory.CreateDirectory(dirPath);&lt;br /&gt;&lt;br /&gt;    file.SaveAs(path);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; applicationUrl = &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}://{1}{2}&amp;quot;&lt;/span&gt;, &lt;br /&gt;&lt;br /&gt;    HttpContext.Request.Url.Scheme,&lt;br /&gt;&lt;br /&gt;    HttpContext.Request.ServerVariables[&lt;span style="color: #006080"&gt;&amp;quot;HTTP_HOST&amp;quot;&lt;/span&gt;],&lt;br /&gt;&lt;br /&gt;      (HttpContext.Request.ApplicationPath.Equals(&lt;span style="color: #006080"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;)) ? &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Empty : HttpContext.Request.ApplicationPath&lt;br /&gt;&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;    image.URL = Path.Combine(applicationUrl, &lt;span style="color: #006080"&gt;&amp;quot;Uploads&amp;quot;&lt;/span&gt;, image.CategoryID.ToString(), fileName);&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (ModelState.IsValid &amp;amp;&amp;amp; image.URL != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    engine.AddImage(image); &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; RedirectToAction(&lt;span style="color: #006080"&gt;&amp;quot;Images&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; { categoryID = image.CategoryID });&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Когда запрос GET выполняется применительно к конечной точке &lt;b&gt;AddImage&lt;/b&gt;, я передаю идентификатор категории как флаг, указывающий, в какую категорию следует включить данное изображение. Запрос POST может выполняться двумя способами: пользователь либо передает существующую ссылку на размещенное где-то изображение, либо загружает собственное изображение на локальный сервер. Когда загрузка идет от клиента на сервер, контент, который нужно поместить на сервер, содержится в &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httppostedfilebase.aspx"&gt;HttpPostedFileBase&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Компонент для такой загрузки в самом представлении создается как форма с поддержкой ввода файла:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&amp;lt;h2&amp;gt;Or you could upload your own file: &amp;lt;/h2&amp;gt;&lt;br /&gt;&lt;br /&gt;@&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Model != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; (Html.BeginForm(&lt;span style="color: #006080"&gt;&amp;quot;AddImage&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Home&amp;quot;&lt;/span&gt;, FormMethod.Post, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; { enctype = &lt;span style="color: #006080"&gt;&amp;quot;multipart/form-data&amp;quot;&lt;/span&gt;, image = Model }))&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    @Html.HiddenFor(model =&amp;gt; model.CategoryID); &lt;br /&gt;&lt;br /&gt;    &amp;lt;input type=&lt;span style="color: #006080"&gt;&amp;quot;file&amp;quot;&lt;/span&gt; name=&lt;span style="color: #006080"&gt;&amp;quot;file&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;input type=&lt;span style="color: #006080"&gt;&amp;quot;submit&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;=&lt;span style="color: #006080"&gt;&amp;quot;OK&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Если никакой файл не выбран, система считает, что пользователь просто решил добавить существующий URL.&lt;/p&gt;

&lt;p&gt;Важно упомянуть, что рабочий процесс загрузки (закачивания на сервер) полагается на наличие папки Upload. Она создается по умолчанию, когда проект развертывается на сервере, но вам нужно убедиться, что у пользователя ASP.NET на компьютере, где находится IIS, имеются соответствующие права на запись в эту папку.&lt;/p&gt;

&lt;h5&gt;Платформа приложений Windows Phone 8&lt;/h5&gt;

&lt;p&gt;Создайте проект нового приложения Windows Phone 8 и добавьте ссылку на &lt;a href="http://weblogs.asp.net/scottgu/archive/2012/08/28/announcing-windows-azure-mobile-services.aspx"&gt;Windows Azure Mobile Services Managed Client&lt;/a&gt;. Она должна быть доступна в разделе Extensions, если вы установили Windows Azure Mobile Services SDK так, как я говорил в начале этой статьи:&lt;/p&gt;

&lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/8473.image_5F00_46358121.png" width="520" height="359" /&gt;&lt;/p&gt;

&lt;p&gt;В &lt;b&gt;App&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;xaml&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;cs&lt;/b&gt; нужно создать экземпляр &lt;a href="http://msdn.microsoft.com/en-us/library/windowsazure/microsoft.windowsazure.mobileservices.mobileserviceclient.aspx"&gt;MobileServiceClient&lt;/a&gt;, который будет действовать как центральная точка подключения к базе данных. Заметьте, что я использую строковые константы AMS и API KEY: 

  &lt;table cellspacing="0" cellpadding="0" border="0"&gt;&lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;
          &lt;p&gt;1&lt;/p&gt;

          &lt;p&gt;2&lt;/p&gt;
        &lt;/td&gt;

        &lt;td&gt;
          &lt;p&gt;public static MobileServiceClient MobileService =&lt;/p&gt;

          &lt;p&gt;new MobileServiceClient(AuthConstants.AmsUrl, AuthConstants.AmsApiKey);&lt;/p&gt;
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;
&lt;/p&gt;

&lt;p&gt;Мобильное приложение также должно содержать модели данных как для категорий, так и для изображений. Вместе с тем их можно слегка реорганизовать для более удобной структуры связывания с данными. Чтобы обеспечить повторное использование классов из разных компонентов приложения, я вновь использую проект &lt;b&gt;Coding&lt;/b&gt;&lt;b&gt;4&lt;/b&gt;&lt;b&gt;Fun&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Lockscreen&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Core&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Создайте новую папку &lt;b&gt;Models&lt;/b&gt; и добавьте новый класс &lt;b&gt;Category&lt;/b&gt;:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Collections.ObjectModel;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; Coding4Fun.Lockscreen.Core.Models&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Category &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Category() &lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      Images = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ObservableCollection&amp;lt;Image&amp;gt;(); &lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;? id { get; set; } &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ObservableCollection&amp;lt;Image&amp;gt; Images { get; set; }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; ToString() &lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Name; &lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Мы по-прежнему полагаемся на &lt;a href="http://msdn.microsoft.com/en-us/library/1t3y8s4s%28v=vs.80%29.aspx"&gt;значение индекса, который может быть null&lt;/a&gt;, но теперь для изображений у нас есть &lt;a href="http://msdn.microsoft.com/en-us/library/ms668604%28v=vs.95%29.aspx"&gt;ObservableCollection&lt;/a&gt;. Причина использования этого специфического типа наборов связана с тем, что при добавлении или удалении элементов обновления привязки к &lt;b&gt;ObservableCollection&lt;/b&gt; выполняются автоматически, а значит, отпадает необходимость в реализации механизма уведомлений.&lt;/p&gt;

&lt;p&gt;Функция ToString переопределена для упрощения выборки данных из связанного объекта. Например, когда набор с категориями будет подключен к списку, мне не придется создавать преобразователь или ссылку на свойство (property link).&lt;/p&gt;

&lt;p&gt;Для модели &lt;b&gt;Image&lt;/b&gt; создайте новый класс с именем &lt;b&gt;Image&lt;/b&gt; в той же папке &lt;b&gt;Models&lt;/b&gt;:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; Coding4Fun.Lockscreen.Core.Models&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Image &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;? id { get; set; }&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; URL { get; set; }&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; Coding4Fun.Lockscreen.Core.Models&lt;br /&gt;&lt;br /&gt;     { &lt;br /&gt;&lt;br /&gt;       &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Image &lt;br /&gt;&lt;br /&gt;       { &lt;br /&gt;&lt;br /&gt;          &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;? id { get; set; }&lt;br /&gt;&lt;br /&gt;          &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; URL { get; set; }&lt;br /&gt;&lt;br /&gt;          &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }&lt;br /&gt;&lt;br /&gt;          &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CategoryID { get; set; } &lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CategoryID { get; set; } &lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;h5&gt;Рабочий процесс и хранилище приложения&lt;/h5&gt;

&lt;p&gt;Давайте поговорим о том, как будут обрабатываться категории изображений в этом приложении. При запуске приложения база данных запрашивается на наличие доступных категорий, и каждый элемент перечисляется на начальном экране. Если пользователь касается одной из категорий, из базы данных запрашиваются изображения, связанные с индексом выбранной категории.&lt;/p&gt;

&lt;p&gt;Однако у пользователя также должна быть возможность создания собственных категорий, которые будут доступны только в рамках данного приложения. Эти категории при необходимости могут включать изображения из множества других категорий с набором исходных ссылок на внутреннее хранилище.&lt;/p&gt;

&lt;p&gt;Так как мы работаем с локальным хранилищем, создадим вспомогательный класс &lt;b&gt;LocalStorageHelper&lt;/b&gt; в проекте &lt;b&gt;Coding&lt;/b&gt;&lt;b&gt;4&lt;/b&gt;&lt;b&gt;Fun&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Lockscreen&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Core&lt;/b&gt; в папке &lt;b&gt;Storage&lt;/b&gt;. Этот класс будет предоставлять базовые функции чтения и записи, позволяющие нам сохранять данные на внутреннем уровне:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; LocalStorageHelper&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; async &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; WriteData(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; folderName, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; fileName, &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[] content) &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;     IStorageFolder rootFolder = ApplicationData.Current.LocalFolder;&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (folderName != &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Empty) &lt;br /&gt;&lt;br /&gt;     { &lt;br /&gt;&lt;br /&gt;       rootFolder = await rootFolder.CreateFolderAsync(folderName, &lt;br /&gt;&lt;br /&gt;       CreationCollisionOption.OpenIfExists); &lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     IStorageFile file = await rootFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; (var s = await file.OpenStreamForWriteAsync())&lt;br /&gt;&lt;br /&gt;     { &lt;br /&gt;&lt;br /&gt;       s.Write(content, 0, content.Length); &lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; async &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ClearFolder(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; folderName)&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    var folder = await ApplicationData.Current.LocalFolder.GetFolderAsync(folderName); &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (folder != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (IStorageFile file &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; await folder.GetFilesAsync()) &lt;br /&gt;&lt;br /&gt;      { &lt;br /&gt;&lt;br /&gt;         await file.DeleteAsync(); &lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; async Task&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; ReadData(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; fileName)&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[] data; &lt;br /&gt;&lt;br /&gt;    StorageFolder folder = ApplicationData.Current.LocalFolder;&lt;br /&gt;&lt;br /&gt;    StorageFile file = await folder.GetFileAsync(fileName);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; (Stream s = await file.OpenStreamForReadAsync())&lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      data = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[s.Length]; &lt;br /&gt;&lt;br /&gt;      await s.ReadAsync(data, 0, (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)s.Length);&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Encoding.UTF8.GetString(data, 0, data.Length);&lt;br /&gt;&lt;br /&gt;   } &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Заметьте, что я использую возможности недавно появившейся функциональности &lt;a href="http://msdn.microsoft.com/library/windows/apps/BR227230"&gt;StorageFolder&lt;/a&gt;/&lt;a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.storagefile.aspx"&gt;StorageFile&lt;/a&gt;. Если вы разрабатывали приложения для Windows Store, то, по-видимому, уже знакомы с этой функциональностью. &lt;b&gt;Application&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Current&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;LocalFolder&lt;/b&gt; дает прямой доступ к локальному каталогу, который можно модифицировать из приложения. Он работает в стиле, аналогичном &lt;b&gt;IsolatedStorageFile&lt;/b&gt; в Windows Phone 7, но более гибок, когда дело доходит до создания новых папок и файлов, а также обеспечивает эффективный обмен файлами.&lt;/p&gt;

&lt;p&gt;Как упоминалось, внутренние данные будут храниться в виде XML. Для этого мне нужен класс с процедурами сериализации и десериализации; кроме того, я могу упростить эту задачу, задействовав функции &lt;b&gt;Serialize&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Save&lt;/b&gt;&lt;b&gt;&amp;lt;&lt;/b&gt;&lt;b&gt;T&lt;/b&gt;&lt;b&gt;&amp;gt;&lt;/b&gt; и &lt;b&gt;Serialize&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Open&lt;/b&gt;&lt;b&gt;&amp;lt;&lt;/b&gt;&lt;b&gt;T&lt;/b&gt;&lt;b&gt;&amp;gt;&lt;/b&gt; из &lt;a href="http://coding4fun.codeplex.com/"&gt;Coding4Fun Toolkit&lt;/a&gt;. Вызовы этих функций обеспечивают гибкую сериализацию, где по умолчанию статический класс ничего не знает о сериализуемом типе, но может логически определять его на основании входящих данных. Как только для контента получена байтовая структура, я записываю ее в файл с помощью &lt;b&gt;LocalStorageHelper&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Поскольку имеется несколько UI-элементов, которые требуют связывания с экземплярами наборов и объектов, в основном проекте предусмотрен класс &lt;b&gt;CentralBindingPoint&lt;/b&gt;, который является моделью основного представления (он реализует &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged%28v=vs.95%29.aspx"&gt;INotifyPropertyChanged&lt;/a&gt;). Этот класс также реализует шаблон Singleton, поэтому основной экземпляр создается при инициализации и потом при необходимости используется повторно:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; Coding4Fun.Lockscreen.Core.Models;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Collections.ObjectModel;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.ComponentModel;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; Coding4Fun.Lockscreen.Mobile&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; CentralBindingPoint : INotifyPropertyChanged &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; CentralBindingPoint instance = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;; &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; padlock = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; CentralBindingPoint()&lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;       Categories = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ObservableCollection&amp;lt;Category&amp;gt;(); &lt;br /&gt;&lt;br /&gt;       CustomCategories = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ObservableCollection&amp;lt;Category&amp;gt;(); &lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; CentralBindingPoint Instance&lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      get&lt;br /&gt;&lt;br /&gt;      { &lt;br /&gt;&lt;br /&gt;         &lt;span style="color: #0000ff"&gt;lock&lt;/span&gt; (padlock) &lt;br /&gt;&lt;br /&gt;         { &lt;br /&gt;&lt;br /&gt;           &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (instance == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) &lt;br /&gt;&lt;br /&gt;           { &lt;br /&gt;&lt;br /&gt;             instance = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; CentralBindingPoint(); &lt;br /&gt;&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;           &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; instance; &lt;br /&gt;&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; ObservableCollection&amp;lt;Category&amp;gt; _categories;&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ObservableCollection&amp;lt;Category&amp;gt; Categories&lt;br /&gt;&lt;br /&gt;     { &lt;br /&gt;&lt;br /&gt;       get&lt;br /&gt;&lt;br /&gt;       { &lt;br /&gt;&lt;br /&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; _categories; &lt;br /&gt;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       set&lt;br /&gt;&lt;br /&gt;       { &lt;br /&gt;&lt;br /&gt;       &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (_categories != &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;) &lt;br /&gt;&lt;br /&gt;       { &lt;br /&gt;&lt;br /&gt;         _categories = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;; &lt;br /&gt;&lt;br /&gt;         NotifyPropertyChanged(&lt;span style="color: #006080"&gt;&amp;quot;Categories&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; ObservableCollection&amp;lt;Category&amp;gt; _customCategories;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ObservableCollection&amp;lt;Category&amp;gt; CustomCategories&lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      get&lt;br /&gt;&lt;br /&gt;      { &lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; _customCategories; &lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      set&lt;br /&gt;&lt;br /&gt;      { &lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (_customCategories != &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;) &lt;br /&gt;&lt;br /&gt;        { &lt;br /&gt;&lt;br /&gt;          _customCategories = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;; &lt;br /&gt;&lt;br /&gt;          NotifyPropertyChanged(&lt;span style="color: #006080"&gt;&amp;quot;CustomCategories&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;        } &lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; Category _currentCategory; &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Category CurrentCategory&lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      get&lt;br /&gt;&lt;br /&gt;      { &lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; _currentCategory; &lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      set&lt;br /&gt;&lt;br /&gt;      { &lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (_currentCategory != &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;) &lt;br /&gt;&lt;br /&gt;        { &lt;br /&gt;&lt;br /&gt;          _currentCategory = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;; &lt;br /&gt;&lt;br /&gt;          NotifyPropertyChanged(&lt;span style="color: #006080"&gt;&amp;quot;CurrentCategory&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;event&lt;/span&gt; PropertyChangedEventHandler PropertyChanged;&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; NotifyPropertyChanged(String info)&lt;br /&gt;&lt;br /&gt;     { &lt;br /&gt;&lt;br /&gt;       &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (PropertyChanged != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) &lt;br /&gt;&lt;br /&gt;       { &lt;br /&gt;&lt;br /&gt;         System.Windows.Deployment.Current.Dispatcher.BeginInvoke( &lt;br /&gt;&lt;br /&gt;           () =&amp;gt;&lt;br /&gt;&lt;br /&gt;           { &lt;br /&gt;&lt;br /&gt;             PropertyChanged(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; PropertyChangedEventArgs(info)); &lt;br /&gt;&lt;br /&gt;           });&lt;br /&gt;&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;На главной странице я создаю &lt;a href="http://msdn.microsoft.com/en-US/library/windowsphone/develop/microsoft.phone.controls.pivot%28v=vs.105%29.aspx"&gt;разметку на основе класса Pivot&lt;/a&gt;, чтобы облегчить переход между веб-наборами (категориями) и локальными наборами:&lt;/p&gt;

&lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/0830.image_5F00_4986F2FC.png" width="292" height="484" /&gt;&lt;/p&gt;

&lt;p&gt;Для каждого из типов наборов существует &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.listbox%28v=vs.95%29.aspx"&gt;ListBox&lt;/a&gt; с собственным &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.datatemplate%28v=VS.95%29.aspx"&gt;DataTemplate&lt;/a&gt;, назначаемым каждому элементу. Элементы извлекаются из &lt;b&gt;Categories&lt;/b&gt; в случае веб-набора и из &lt;b&gt;CustomCategories&lt;/b&gt; в случае локальных наборов — все это делается в модели представления &lt;b&gt;CentralBindingPoint&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Категории загружаются с помощью класса &lt;b&gt;DataEngine&lt;/b&gt;, который я добавил в папку Data в основном проекте приложения. Это оболочка для операций над данными через Azure Mobile Services, позволяющая комбинировать список категорий и изображения при условии, что известен индекс категории:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DataEngine&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  async &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Task&amp;lt;List&amp;lt;Category&amp;gt;&amp;gt; GetCategoryList() &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    IMobileServiceTable&amp;lt;Category&amp;gt; table = App.MobileService.GetTable&amp;lt;Category&amp;gt;(); &lt;br /&gt;&lt;br /&gt;    List&amp;lt;Category&amp;gt; data = await table.ToListAsync();&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; data;&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  async &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Task&amp;lt;List&amp;lt;Image&amp;gt;&amp;gt; GetImagesByCategoryId(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; categoryId)&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    IMobileServiceTable&amp;lt;Image&amp;gt; table = App.MobileService.GetTable&amp;lt;Image&amp;gt;(); &lt;br /&gt;&lt;br /&gt;    List&amp;lt;Image&amp;gt; data = await table.Where(x =&amp;gt; x.CategoryID == categoryId).ToListAsync();&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; data;&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Когда загружается основная страница, с помощью локального экземпляра &lt;b&gt;DataEngine&lt;/b&gt; я вызываю &lt;b&gt;GetCategoryList&lt;/b&gt; и получаю набор List&amp;lt;Category&amp;gt;, который потом преобразуется в &lt;b&gt;ObservableCollection&lt;/b&gt; через один из конструкторов по умолчанию:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;async &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; MainPage_Loaded(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  CentralBindingPoint.Instance.Categories = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ObservableCollection&amp;lt;Category&amp;gt;(await dataEngine.GetCategoryList()); &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Если в списке веб-наборов выбрана какая-то категория, я назначаю выбранный элемент текущей категорией и перехожу на страницу &lt;b&gt;ImageSetPage&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;xaml&lt;/b&gt;, которая будет отображать связанные изображения:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;async &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ListBox_SelectionChanged_1(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; sender, System.Windows.Controls.SelectionChangedEventArgs e)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  var box = (ListBox)sender;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (box.SelectedItem != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    Category selectedCategory = (Category)box.SelectedItem; &lt;br /&gt;&lt;br /&gt;    selectedCategory.Images = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ObservableCollection&amp;lt;Coding4Fun.Lockscreen.Core.Models.Image&amp;gt;&lt;br /&gt;&lt;br /&gt;      (await dataEngine.GetImagesByCategoryId((&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)selectedCategory.id));&lt;br /&gt;&lt;br /&gt;    CentralBindingPoint.Instance.CurrentCategory = selectedCategory;&lt;br /&gt;&lt;br /&gt;    NavigationService.Navigate(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Uri(&lt;span style="color: #006080"&gt;&amp;quot;/ImageSetPage.xaml&amp;quot;&lt;/span&gt;, UriKind.Relative));&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Заметьте, что изображения не загружаются в тот же момент, что и категории; вместо этого они загружаются, только когда категория выбрана, — с этим и связан вызов &lt;b&gt;GetImagesByCategoryId&lt;/b&gt; при выборе.&lt;/p&gt;

&lt;p&gt;Для собственного набора процедура почти идентична с тем лишь отличием, что ссылки на изображения уже имеются, так как они были десериализованы из локального хранилища:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; lstCustomSets_SelectionChanged_1(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; sender, SelectionChangedEventArgs e)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  var box = (ListBox)sender;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (box.SelectedItem != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    Category selectedCategory = (Category)box.SelectedItem; &lt;br /&gt;&lt;br /&gt;    CentralBindingPoint.Instance.CurrentCategory = selectedCategory;&lt;br /&gt;&lt;br /&gt;    NavigationService.Navigate(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Uri(&lt;span style="color: #006080"&gt;&amp;quot;/ImageSetPage.xaml&amp;quot;&lt;/span&gt;, UriKind.Relative));&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;В &lt;b&gt;ImageSetPage&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;xaml&lt;/b&gt; я использую &lt;b&gt;ListBox&lt;/b&gt; с &lt;b&gt;WrapPanel&lt;/b&gt; в &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.itemspaneltemplate.aspx"&gt;ItemsPanelTemplate&lt;/a&gt;, гарантирующем, что в строке будет не более двух изображений, а любые добавленные картинки будут переноситься на другую строку с фиксированной длиной. Такой функционал вы можете получить от &lt;a href="http://phone.codeplex.com/"&gt;WPToolkit&lt;/a&gt; (ранее известный как Silverlight Toolkit for Windows Phone, &lt;a href="https://nuget.org/packages/WPtoolkit"&gt;доступный в NuGet&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/1641.image_5F00_6B231BCD.png" width="292" height="484" /&gt;&lt;/p&gt;

&lt;p&gt;Вот основная XAML-разметка:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ListBox&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #ff0000"&gt;SelectionMode&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Single&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #ff0000"&gt;Margin&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;24&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #ff0000"&gt;x:Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;lstImages&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;SelectionChanged&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;lstImages_SelectionChanged_1&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #ff0000"&gt;ItemsSource&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;{Binding Path=Instance.CurrentCategory.Images,&lt;br /&gt;&lt;br /&gt;Source={StaticResource CentralBindingPoint}}&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #ff0000"&gt;ItemTemplate&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;{StaticResource ListItemTemplate}&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ListBox.ItemsPanel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ItemsPanelTemplate&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;toolkit:WrapPanel&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ItemWidth&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;216&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ItemHeight&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;260&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;ItemsPanelTemplate&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;ListBox.ItemsPanel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;ListBox&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Теперь, когда у нас есть скелет кода для обработки входных данных, посмотрим, как его можно трансформировать в активный экран блокировки, на котором могут циклически меняться фоновые обои. На странице &lt;b&gt;ImageSetPage&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;xaml&lt;/b&gt; в панели приложения имеется кнопка, позволяющая задавать текущую категорию в качестве источника этих фоновых обоев.&lt;/p&gt;

&lt;p&gt;В данный момент каждый экземпляр &lt;b&gt;Image&lt;/b&gt; содержит URL изображения, а сами изображения могут быть размещены где угодно вне приложения. Однако это может вызвать проблемы в процессе вывода обоев, поскольку API разрешает устанавливать в качестве фона только локально хранящиеся изображения. То есть мне нужно скачивать каждое изображение в локальную папку приложения:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;private async void btnSetStack_Click_1(object sender, EventArgs e)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  var isProvider = Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication;&lt;br /&gt;&lt;br /&gt;  if (!isProvider) &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    var op = await Windows.Phone.System.UserProfile.LockScreenManager.RequestAccessAsync(); &lt;br /&gt;&lt;br /&gt;    isProvider = op == Windows.Phone.System.UserProfile.LockScreenRequestResult.Granted;&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (isProvider)&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    downloadableItems = new List&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;string&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;(); &lt;br /&gt;&lt;br /&gt;    fileItems = new List&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;string&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;    foreach (var image in CentralBindingPoint.Instance.CurrentCategory.Images) &lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      downloadableItems.Add(image.URL); &lt;br /&gt;&lt;br /&gt;      fileItems.Add(Path.GetFileName(image.URL)); &lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    SerializationHelper.SerializeToFile(fileItems, &amp;quot;imagestack.xml&amp;quot;);&lt;br /&gt;&lt;br /&gt;    LocalStorageHelper.ClearFolder(&amp;quot;CurrentSet&amp;quot;);&lt;br /&gt;&lt;br /&gt;    DownloadImages();&lt;br /&gt;&lt;br /&gt;    grdDownloading.Visibility = System.Windows.Visibility.Visible;&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Прежде всего, надо убедиться в том, что приложение способно устанавливать фон для экрана блокировки и зарегистрировано в ОС как провайдер. Приложение должно заявить о своем намерении получать доступ к обоям, и для этого в &lt;b&gt;WMAppManifest&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;xml&lt;/b&gt; требуется добавить следующий фрагмент кода сразу под узлом &lt;b&gt;Tokens&lt;/b&gt;:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Extensions&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Extension&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ExtensionName&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;LockScreen_Background&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ConsumerID&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;{111DFF24-AA15-4A96-8006-2BFF8122084F}&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;TaskID&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;_default&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Extensions&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Набор &lt;b&gt;downloadableItems&lt;/b&gt; представляет очередь скачивания (download queue), а &lt;b&gt;fileItems&lt;/b&gt; содержит имена локальных файлов для каждого изображения, которое предполагается скачать, сериализовать и использовать в фоновом агенте для перебора файлов в данной категории. Всякий раз, когда начинается процесс скачивания, на экране становится видимым накладной элемент, уведомляющий пользователя о процессе получения изображения.&lt;/p&gt;

&lt;p&gt;Кроме того, обратите внимание на тот факт, что я вызываю &lt;b&gt;LocalStorageHelper&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;ClearFolder&lt;/b&gt;, передавая имя папки как первый аргумент. Я не хочу хранить изображения для неактивных наборов, поэтому, когда выби��ается новый набор, хранившиеся до этого момента изображения удаляются из папки &lt;b&gt;CurrentSet&lt;/b&gt; и заменяются теми, которые скачиваются для нового набора. Реализация функции &lt;b&gt;ClearFolder&lt;/b&gt; выглядит так:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ClearFolder(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; folderName&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (store.DirectoryExists(folderName)) &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; file &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; store.GetFileNames(folderName + &lt;span style="color: #006080"&gt;&amp;quot;\\*.*&amp;quot;&lt;/span&gt;)) &lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      store.DeleteFile(folderName + &amp;quot;\\&amp;quot; + file); &lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;После сохранения имен файлов в &lt;b&gt;imagestack&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;xml&lt;/b&gt; изображения скачиваются с помощью &lt;b&gt;DownloadImages&lt;/b&gt;:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DownloadImages()&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  WebClient client = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; WebClient(); &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; fileName = Path.GetFileName(downloadableItems.First());&lt;br /&gt;&lt;br /&gt;  client.OpenReadAsync(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Uri(downloadableItems.First()));&lt;br /&gt;&lt;br /&gt;  client.OpenReadCompleted += (sender, args) =&amp;gt;&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    Debug.WriteLine(&lt;span style="color: #006080"&gt;&amp;quot;Downloaded &amp;quot;&lt;/span&gt; + fileName); &lt;br /&gt;&lt;br /&gt;    LocalStorageHelper.WriteData(&lt;span style="color: #006080"&gt;&amp;quot;CurrentSet&amp;quot;&lt;/span&gt;, fileName, StreamToByteArray(args.Result));&lt;br /&gt;&lt;br /&gt;    downloadableItems.Remove(downloadableItems.First());&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (downloadableItems.Count != 0)&lt;br /&gt;&lt;br /&gt;      DownloadImages();&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      grdDownloading.Visibility = System.Windows.Visibility.Collapsed; &lt;br /&gt;&lt;br /&gt;      LocalStorageHelper.CycleThroughImages();&lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #008000"&gt;//ScheduledActionService.LaunchForTest(&amp;quot;LockscreenChanger&amp;quot;, TimeSpan.FromSeconds(5));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;  };&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Здесь видно, что я вызываю &lt;b&gt;LocalStorageHelper&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;CycleThroughImages&lt;/b&gt; — функцию, которая считывает файл, содержащий текущий набор, и извлекает первое изображение, назначая его в качестве текущих обоев, затем перемещает его в конец списка, чтобы сменить на следующее, и весь процесс повторяется:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; CycleThroughImages()&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  List&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; images = Coding4Fun.Phone.Storage.Serialize.Open&amp;lt;List&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt;&amp;gt;(&lt;span style="color: #006080"&gt;&amp;quot;imagestack.xml&amp;quot;&lt;/span&gt;); &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (images != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; tempImage = images.First(); &lt;br /&gt;&lt;br /&gt;    Uri currentImageUri = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Uri(&lt;span style="color: #006080"&gt;&amp;quot;ms-appdata:///Local/CurrentSet/&amp;quot;&lt;/span&gt; + tempImage, UriKind.Absolute);&lt;br /&gt;&lt;br /&gt;    Windows.Phone.System.UserProfile.LockScreen.SetImageUri(currentImageUri);&lt;br /&gt;&lt;br /&gt;    images.Remove(tempImage);&lt;br /&gt;&lt;br /&gt;    images.Add(tempImage);&lt;br /&gt;&lt;br /&gt;    Coding4Fun.Phone.Storage.Serialize.Save&amp;lt;List&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt;&amp;gt;(&lt;span style="color: #006080"&gt;&amp;quot;imagestack.xml&amp;quot;&lt;/span&gt;, images);&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Возможно, вас интересует, почему я не пользуюсь для этого &lt;a href="http://msdn.microsoft.com/en-us/library/7977ey2c.aspx"&gt;Queue&amp;lt;T&amp;gt;&lt;/a&gt;. В конце концов, &lt;b&gt;Enqueue&lt;/b&gt; и &lt;b&gt;Dequeue&lt;/b&gt; могли бы немного упростить мне работу. Проблема в том, что экземпляр Queue нельзя сериализовать напрямую без преобразования в линейный список. А я придерживаюсь использования минимальных ресурсов в обработке и поэтому оперирую экземпляром &lt;b&gt;List&lt;/b&gt;&lt;b&gt;&amp;lt;&lt;/b&gt;&lt;b&gt;T&lt;/b&gt;&lt;b&gt;&amp;gt;&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Рекурсивный метод скачивания изображений выполняется, пока не опустеет очередь на скачивание, после чего накладной элемент исчезает с экрана.&lt;/p&gt;

&lt;h5&gt;Фоновый агент&lt;/h5&gt;

&lt;p&gt;К этому моменту у нас есть локально сохраненные изображения, и они перечислены в XML-файле. Если пользователь принимает предложение системы, приложение также регистрируется как провайдер фоновых изображений экрана блокировки, но пока у нас нет кода, отвечающего за цикл смены обоев. Для этого создайте в своем решении новый проект Background Agent. Я назвал свой так: &lt;b&gt;Coding&lt;/b&gt;&lt;b&gt;4&lt;/b&gt;&lt;b&gt;Fun&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Lockscreen&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Agent&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Функция &lt;b&gt;OnInvoke&lt;/b&gt; в &lt;b&gt;ScheduledAgent&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;cs&lt;/b&gt; выполняется с интервалом в 30 минут. Это временной лимит, определенный типом фонового агента &lt;a href="http://msdn.microsoft.com/en-US/library/windowsphone/develop/microsoft.phone.scheduler.periodictask%28v=vs.105%29.aspx"&gt;PeriodicTask&lt;/a&gt;, который мы будем использовать здесь. Вам нужно добавить следующий фрагмент кода:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; OnInvoke(ScheduledTask task)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;var isProvider = Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication; &lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (isProvider)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;LocalStorageHelper.CycleThroughImages(); &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;NotifyComplete();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Как и во фрагменте со скачиванием, я проверяю, что перед попыткой смены обоев приложение является зарегистрированным провайдером. В ином случае будет сгенерировано исключение, и фоновый агент рухнет. Скверно то, что в случае двух сбоев подряд периодически выполняемой задачи она удаляется из очереди задач и фоновые изображения меняться не будут.&lt;/p&gt;

&lt;p&gt;Если приложение является провайдером, вызовите &lt;b&gt;CycleThroughImages&lt;/b&gt;, чтобы задать новый фон и переместить старый в конец списка. Чтобы быть уверенным в выборе разных изображений, исходный десериализованный список модифицируется: первое изображение становится последним, остальные изображения в стеке продвигаются вверх, а после этого список сериализуется обратно в &lt;b&gt;imagestack&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;xml&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Фоновый агент нужно зарегистрировать в &lt;b&gt;WMAppManifest&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;xml&lt;/b&gt;. Добавьте ExtendedTask в узел Tasks: &lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ExtendedTask&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;LockscreenChangerTask&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;BackgroundServiceAgent&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Specifier&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;ScheduledTaskAgent&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #ff0000"&gt;Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;LockscreenChanger&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #ff0000"&gt;Source&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Coding4Fun.Lockscreen.Agent&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #ff0000"&gt;Type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Coding4Fun.Lockscreen.Agent.ScheduledAgent&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;ExtendedTask&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Кроме того, при запуске приложения вы должны убедиться, что задача зарегистрирована (если это не так, зарегистрируйте ее). Для этого используйте обработчик события Application_Launching: &lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Application_Launching(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; sender, LaunchingEventArgs e)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; taskName = &lt;span style="color: #006080"&gt;&amp;quot;LockscreenChanger&amp;quot;&lt;/span&gt;; &lt;br /&gt;&lt;br /&gt;  var oldTask = ScheduledActionService.Find(taskName) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; PeriodicTask;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (oldTask != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    ScheduledActionService.Remove(taskName); &lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  PeriodicTask task = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; PeriodicTask(taskName);&lt;br /&gt;&lt;br /&gt;  task.Description = &lt;span style="color: #006080"&gt;&amp;quot;Change lockscreen wallpaper.&amp;quot;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;  ScheduledActionService.Add(task); &lt;br /&gt;&lt;br /&gt;  LoadCustomCategories(); &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Здесь &lt;b&gt;LoadCustomCategories&lt;/b&gt; будет десериализовать существующие собственные категории, чтобы их можно было показывать на основной странице после запуска приложения: &lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; async &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; LoadCustomCategories()&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;try&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    CentralBindingPoint.Instance.CustomCategories = &lt;br /&gt;&lt;br /&gt;      (ObservableCollection&amp;lt;Category&amp;gt;)await SerializationHelper.DeserializeFromFile(&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(ObservableCollection&amp;lt;Category&amp;gt;), &lt;span style="color: #006080"&gt;&amp;quot;customcat.xml&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;     Debug.WriteLine(&lt;span style="color: #006080"&gt;&amp;quot;No customcat.xml - no registered custom categories.&amp;quot;&lt;/span&gt;); &lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Теперь фоновые изображения будут автоматически сменяться на основе веб-наборов, которые вы будете активировать через каждые 30 минут.&lt;/p&gt;

&lt;h5&gt;Работа с собственными категориями&lt;/h5&gt;

&lt;p&gt;Давайте создадим несколько собственных наборов. Для контроля пользовательского ввода я применяю элемент управления &lt;b&gt;CustomMessageBox&lt;/b&gt;, доступный в &lt;a href="http://phone.codeplex.com/"&gt;Windows Phone Toolkit&lt;/a&gt;. Он достаточно гибок и позволяет выбирать между добавлением элемента управления &lt;b&gt;TextBox&lt;/b&gt; (для создания новой категории) и использованием &lt;b&gt;ListPicker&lt;/b&gt; (для отображения имеющихся собственных категорий в соответствующей UI-разметке).&lt;/p&gt;

&lt;p&gt;Когда пользователь решает создать новую категорию, он касается кнопки «плюс» в панели приложения на основной странице:&lt;/p&gt;

&lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/8358.image_5F00_78E53BFB.png" width="247" height="410" /&gt;&lt;/p&gt;

&lt;p&gt;Реализация весьма проста:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; btnSetStack_Click_1(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  TextBox textBox = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; TextBox(); &lt;br /&gt;&lt;br /&gt;  CustomMessageBox box = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; CustomMessageBox()&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    Caption = &lt;span style="color: #006080"&gt;&amp;quot;Add Custom Category&amp;quot;&lt;/span&gt;, &lt;br /&gt;&lt;br /&gt;    Message = &lt;span style="color: #006080"&gt;&amp;quot;Enter a unique name for the new category.&amp;quot;&lt;/span&gt;,&lt;br /&gt;&lt;br /&gt;    LeftButtonContent = &lt;span style="color: #006080"&gt;&amp;quot;ok&amp;quot;&lt;/span&gt;,&lt;br /&gt;&lt;br /&gt;    RightButtonContent = &lt;span style="color: #006080"&gt;&amp;quot;cancel&amp;quot;&lt;/span&gt;,&lt;br /&gt;&lt;br /&gt;    Content = textBox&lt;br /&gt;&lt;br /&gt;  };&lt;br /&gt;&lt;br /&gt;  box.Dismissed += (s, boxEventArgs) =&amp;gt;&lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (boxEventArgs.Result == CustomMessageBoxResult.LeftButton) &lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.IsNullOrWhiteSpace(textBox.Text)) &lt;br /&gt;&lt;br /&gt;      { &lt;br /&gt;&lt;br /&gt;        var categoryCheck = (from c &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; CentralBindingPoint.Instance.CustomCategories &lt;br /&gt;&lt;br /&gt;          &lt;span style="color: #0000ff"&gt;where&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;          c.Name == textBox.Text&lt;br /&gt;&lt;br /&gt;          select c).FirstOrDefault();&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (categoryCheck == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;        { &lt;br /&gt;&lt;br /&gt;          Category category = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Category() { Name = textBox.Text };&lt;br /&gt;&lt;br /&gt;          CentralBindingPoint.Instance.CustomCategories.Add(category);&lt;br /&gt;&lt;br /&gt;          Coding4Fun.Toolkit.Storage.Serialize.Save&amp;lt;ObservableCollection&amp;lt;Category&amp;gt;&amp;gt;(&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #006080"&gt;&amp;quot;customcat.xml&amp;quot;&lt;/span&gt;, CentralBindingPoint.Instance.CustomCategories);&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        { &lt;br /&gt;&lt;br /&gt;           MessageBox.Show(&lt;span style="color: #006080"&gt;&amp;quot;Add Custom Category&amp;quot;&lt;/span&gt;, &lt;br /&gt;&lt;br /&gt;           &lt;span style="color: #006080"&gt;&amp;quot;This category name was already taken!&amp;quot;&lt;/span&gt;,&lt;br /&gt;&lt;br /&gt;           MessageBoxButton.OK);&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;    } &lt;br /&gt;&lt;br /&gt;  };&lt;br /&gt;&lt;br /&gt;  box.Show(); &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Когда окно сообщения удаляется, я проверяю, какая кнопка была нажата, чтобы предпринять соответствующие действия. Предположим, что пользователь решил добавить новую категорию. В этом случае надо проверить, что в существующем наборе нет категории с тем же названием. Если ее нет, создается новый экземпляр &lt;b&gt;Category&lt;/b&gt;, добавляется в набор в модель главного представления и сериализуется в &lt;b&gt;customcat&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;xml&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;У пользователя также должна быть возможность добавлять изображения из любой категории в собственную. Для этого я решил предоставить вариант переноса названия и URL изображения, когда пользователь касается изображения в &lt;b&gt;ImageSetPage&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;xaml&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Помните: если на данный момент не зарегистрирована ни одна собственная категория, пользователя следует уведомить о том, что он должен сначала создать такую категорию, поэтому альтернативным путем в диалоге с возможностью выбора названия собственной категории должно быть оповещение через окно сообщения:&lt;/p&gt;

&lt;p&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/5618.image_5F00_16E349F0.png" width="268" height="444" /&gt;&lt;/p&gt;

&lt;p&gt;Вот фрагмент кода, который именно это и делает:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;
  &lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; lstImages_SelectionChanged_1(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; sender, SelectionChangedEventArgs e)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (CentralBindingPoint.Instance.CustomCategories.Count &amp;gt; 0) &lt;br /&gt;&lt;br /&gt;  { &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (lstImages.SelectedItem != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) &lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      ListPicker picker = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ListPicker() &lt;br /&gt;&lt;br /&gt;      { &lt;br /&gt;&lt;br /&gt;        Header = &lt;span style="color: #006080"&gt;&amp;quot;Custom category name:&amp;quot;&lt;/span&gt;, &lt;br /&gt;&lt;br /&gt;        ItemsSource = CentralBindingPoint.Instance.CustomCategories,&lt;br /&gt;&lt;br /&gt;        Margin = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Thickness(12, 42, 24, 18)&lt;br /&gt;&lt;br /&gt;      };&lt;br /&gt;&lt;br /&gt;      CustomMessageBox messageBox = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; CustomMessageBox()&lt;br /&gt;&lt;br /&gt;      { &lt;br /&gt;&lt;br /&gt;        Caption = &lt;span style="color: #006080"&gt;&amp;quot;Add To Custom Category&amp;quot;&lt;/span&gt;, &lt;br /&gt;&lt;br /&gt;        Message = &lt;span style="color: #006080"&gt;&amp;quot;Select a registered custom category to add this image to.&amp;quot;&lt;/span&gt;,&lt;br /&gt;&lt;br /&gt;        Content = picker,&lt;br /&gt;&lt;br /&gt;        LeftButtonContent = &lt;span style="color: #006080"&gt;&amp;quot;ok&amp;quot;&lt;/span&gt;,&lt;br /&gt;&lt;br /&gt;        RightButtonContent = &lt;span style="color: #006080"&gt;&amp;quot;cancel&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;      };&lt;br /&gt;&lt;br /&gt;      messageBox.Dismissing += (s, boxEventArgs) =&amp;gt;&lt;br /&gt;&lt;br /&gt;      { &lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (picker.ListPickerMode == ListPickerMode.Expanded) &lt;br /&gt;&lt;br /&gt;      { &lt;br /&gt;&lt;br /&gt;        boxEventArgs.Cancel = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;; &lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    messageBox.Dismissed += (s2, e2) =&amp;gt;&lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;switch&lt;/span&gt; (e2.Result) &lt;br /&gt;&lt;br /&gt;    { &lt;br /&gt;&lt;br /&gt;      &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; CustomMessageBoxResult.LeftButton: &lt;br /&gt;&lt;br /&gt;      { &lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (picker.SelectedItem != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) &lt;br /&gt;&lt;br /&gt;        { &lt;br /&gt;&lt;br /&gt;          Category category = (from c &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; CentralBindingPoint.Instance.CustomCategories &lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;where&lt;/span&gt; c.Name == picker.SelectedItem.ToString()&lt;br /&gt;&lt;br /&gt;            select c).FirstOrDefault();&lt;br /&gt;&lt;br /&gt;          &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (category != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;          { &lt;br /&gt;&lt;br /&gt;             category.Images.Add((Coding4Fun.Lockscreen.Core.Models.Image)lstImages.SelectedItem); &lt;br /&gt;&lt;br /&gt;             Coding4Fun.Toolkit.Storage.Serialize.Save&amp;lt;ObservableCollection&amp;lt;Category&amp;gt;&amp;gt;(&lt;br /&gt;&lt;br /&gt;                &lt;span style="color: #006080"&gt;&amp;quot;customcat.xml&amp;quot;&lt;/span&gt;, CentralBindingPoint.Instance.CustomCategories);&lt;br /&gt;&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;           lstImages.SelectedItem = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;           lstImages.IsEnabled = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;          &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; CustomMessageBoxResult.RightButton: &lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; CustomMessageBoxResult.None:&lt;br /&gt;&lt;br /&gt;        { &lt;br /&gt;&lt;br /&gt;          lstImages.SelectedItem = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;; &lt;br /&gt;&lt;br /&gt;          &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    messageBox.Show();&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;  MessageBox.Show(&lt;span style="color: #006080"&gt;&amp;quot;Add To Custom Category&amp;quot;&lt;/span&gt;, &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #006080"&gt;&amp;quot;Tapping on an image will prompt you to add it to a custom category&amp;quot;&lt;/span&gt; + Environment.NewLine +&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #006080"&gt;&amp;quot;Seems like you don't have any custom categories yet.&amp;quot;&lt;/span&gt;, MessageBoxButton.OK); &lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Как только категория выбрана из списка, изображение добавляется в набор Images в экземпляре &lt;b&gt;Category&lt;/b&gt;, и список категорий сериализуется для сохранения изменений. Никаких ограничений на то, из каких категорий можно выбирать изображения в другие категории, нет — можно даже выбирать изображения из собственных категорий и включать их в другие категории. Кроме того, изображение можно неоднократно добавлять в одну и ту же категорию.&lt;/p&gt;

&lt;h5&gt;Заключение&lt;/h5&gt;

&lt;p&gt;С помощью Azure Mobile Services и управляемого SDK, доступного для Windows Phone, а также открытого REST API сравнительно легко создавать подключенные приложения для нескольких платформ одновременно без существенной переработки логики и кодовой базы.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10419259" width="1" height="1"&gt;</content><author><name>Russian MSDN</name><uri>http://blogs.msdn.com/Russian-MSDN/ProfileUrlRedirect.ashx</uri></author><category term="ASP.Net MVC" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/ASP-Net+MVC/" /><category term="Windows Phone" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/Windows+Phone/" /><category term="Windows Azure" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/Windows+Azure/" /><category term="Windows Phone 8" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/Windows+Phone+8/" /></entry><entry><title>Что общего между Имперским маршем, Windows Phone 8, Netduino, Bluetooth и сонаром?</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/rucoding4fun/archive/2013/04/03/what-does-the-imperial-march-windows-phone-8-netduino-bluetooth-and-sonar-have-in-common-this.aspx" /><id>http://blogs.msdn.com/b/rucoding4fun/archive/2013/04/03/what-does-the-imperial-march-windows-phone-8-netduino-bluetooth-and-sonar-have-in-common-this.aspx</id><published>2013-04-03T17:40:28Z</published><updated>2013-04-03T17:40:28Z</updated><content type="html">&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://channel9.msdn.com/Niners/gduncan411"&gt;Грэг Дункан&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Сегодняшний проект возвращает нас к недавнему сообщению «&lt;a href="http://blogs.msdn.com/b/rucoding4fun/archive/2013/02/27/windows-phone-8-netduino-and-bluetooth.aspx"&gt;Windows Phone 8, Netduino и Bluetooth...&lt;/a&gt;», очень классной разработке Мэта Каванага (Matt Cavanagh). Крис Уолкер (&lt;a href="http://forums.netduino.com/index.php?/user/2-chris-walker/"&gt;Chris Walker&lt;/a&gt;) известный в сообществе &lt;a href="http://netduino.com/"&gt;Netduino&lt;/a&gt; был настолько впечатлен, что связался с нами и отметил замечательную работу Мэта, которую он выполняет сейчас.&lt;/p&gt;  &lt;p&gt;Я имею в виду, как вы не нарыли проект, объединяющий Windows Phone 8, Netduino, сонар and the Имперский марш из Звездных войн!?&lt;/p&gt;  &lt;p&gt;Но сначала...&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog.roguecode.co.za/Post/MoreNetduino%2bWP8%2bBluetoothfun-3Dreconstruction"&gt;&lt;b&gt;Еще &lt;/b&gt;&lt;b&gt;Netduino&lt;/b&gt;&lt;b&gt; + &lt;/b&gt;&lt;b&gt;WP&lt;/b&gt;&lt;b&gt;8 + &lt;/b&gt;&lt;b&gt;Bluetooth&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;развлечение – 3D-реконструкция&lt;/b&gt;&lt;/a&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;Продолжая свой предыдущий пост &lt;a href="http://blog.roguecode.co.za/Post/ControllingaNetduinooverBluetoothwithWP8"&gt;Bluetooth с Netduino&lt;/a&gt;, я решил немного расширить его.&lt;/p&gt;    &lt;p&gt;Цель проекта следующая: Netduino посылает данные об ориентации (XYZ) через Bluetooth к WP8, который отображает трехмерное его представление (конечно, под правильным углом), и, в качестве бонуса, подсоединенный потенциометр управляет увеличением.&lt;/p&gt;    &lt;p&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/WKoQXQmYC3c&amp;amp;hl=en"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/WKoQXQmYC3c&amp;amp;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;    &lt;p&gt;&lt;i&gt;Как и на предыдущем видео &lt;/i&gt;&lt;i&gt;Netduino &lt;/i&gt;&lt;i&gt;питается от &lt;/i&gt;&lt;i&gt;USB&lt;/i&gt;&lt;i&gt;-разъема? Поскольку у меня под рукой не оказалось 9-вольтовой батареи. И можно заметить запаздывание на несколько мс из-за сглаживающих фильтров. Можно получить движение практически в реальном времени (&lt;/i&gt;&lt;i&gt;Bluetooth &lt;/i&gt;&lt;i&gt;очень быстрый), но тогда вы также получите всевозможные флуктуации от акселерометра.&lt;/i&gt;&lt;/p&gt;    &lt;p&gt;&lt;i&gt;...&lt;/i&gt;&lt;/p&gt;    &lt;p&gt;Для телефонного приложения я скопировал порядочный кусок кода из предыдущего поста. Часть была закомментирована, т. к. относится к интерфейсу пользователя, не используемому в данном проекте. Поскольку предыдущий пост раскрывал все эти темы, я не собираюсь объяснять их заново.&lt;/p&gt;    &lt;p&gt;Итак, как мы показываем трехмерную модель? По моему мнению, самый простой путь – это XNA. Однако Microsoft ликвидировала XNA в WP8 (и W8), оставив лишь неуправляемый код. Выход – MonoGame. &lt;a href="http://monogame.codeplex.com/"&gt;MonoGame – это инфраструктура&lt;/a&gt;, позволяющая разработчикам написать единую базу кода и заставить ее работать на множестве разных платформ. Так что даже хотя XNA официально не поддерживается на WP8, по-прежнему можно использовать MonoGame, которая достаточно актуальна (по крайней мере, в том, что мы собираемся сделать). Вот объяснение этому:&lt;/p&gt;    &lt;p&gt;...&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Да, да, я знаю, «Звездные войны!...», приступаем…&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog.roguecode.co.za/Post/Netduino%2bSonar%2bWP8%2bBluetooth-Controllingsoundwithyourmind"&gt;&lt;b&gt;Netduino &lt;/b&gt;&lt;b&gt;+ &lt;/b&gt;&lt;b&gt;Sonar &lt;/b&gt;&lt;b&gt;+ &lt;/b&gt;&lt;b&gt;WP8 &lt;/b&gt;&lt;b&gt;+ &lt;/b&gt;&lt;b&gt;Bluetooth &lt;/b&gt;&lt;b&gt;=&lt;/b&gt;&lt;b&gt; управление звуком с помощью мысли&lt;/b&gt;&lt;/a&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/jtNh3nvP8xo&amp;amp;hl=en"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/jtNh3nvP8xo&amp;amp;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;    &lt;p&gt;О’кей, может не с помощью мысли, но, по крайней мере, с помощью руки.&lt;/p&gt;    &lt;p&gt;&lt;b&gt;Цель – &lt;/b&gt;добавить ультразвуковой сонар к Netduino, определяющий насколько близко находится рука, и передать эту информацию через Bluetooth к Windows Phone 8, чтобы последний отобразил ее. В качестве награды можно сделать что-то полезное с данными (например, управление громкостью Имперского марша очень полезно!)&lt;b&gt;&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;&lt;b&gt;Для этого нужно:&lt;/b&gt;&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;Netduino или его вариант &lt;/li&gt;      &lt;li&gt;Ультразвуковой датчик &lt;/li&gt;      &lt;li&gt;Модуль Bluetooth &lt;/li&gt;      &lt;li&gt;Windows Phone 8 &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;...&lt;/p&gt;    &lt;p&gt;Несколько месяцев назад я приобрел такой ультразвуковой датчик: HC-SR04 (&lt;a href="http://lightake.com/detail.do/sku.Ultrasonic_Sensor_HC_SR04_Distance_Measuring_Module___Blue___Silver-58594"&gt;http://lightake.com/detail.do/sku.Ultrasonic&lt;i&gt;Sensor&lt;/i&gt;HC&lt;i&gt;SR04&lt;/i&gt;Distance&lt;i&gt;Measuring&lt;/i&gt;Module&lt;b&gt;&lt;i&gt;Blue&lt;/i&gt;&lt;/b&gt;Silver-58594&lt;/a&gt;). Я купил его в случайном маленьком онлайновом китайском магазине за 4 долл. Я приобрел его, чтобы увидеть действительно ли его доставят (бесплатно по всему миру) так как там был большой набор датчиков для Arduino и Netduino, а у нас сложно получить их. Удивительно, но заказ пришел.&lt;/p&gt;    &lt;p&gt;Так что я вечером я распаковал их, &lt;a href="https://twitter.com/RogueCode/status/301031128452702208"&gt;твитнул&lt;/a&gt; и подключил к Netduino.&lt;/p&gt;    &lt;p&gt;VCC – 5v      &lt;br /&gt;Trig – D6       &lt;br /&gt;Echo – D7       &lt;br /&gt;GND – GND&lt;/p&gt;    &lt;p&gt;На этом сайте прекрасно объясняется как они работают: &lt;a href="http://arduino-info.wikispaces.com/UltraSonicDistance"&gt;http://arduino-info.wikispaces.com/UltraSonicDistance&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;i&gt;Сонар имеет два датчика: динамик и микрофон. Ультразвук – это высокочастотный звук (обычно 40 КГц ). Короткий цуг звуковых волн (обычно лишь восемь периодов) посылается через излучатель (на рисунке слева). Затем приемник слушает эхо. Таким образом, принцип ультразвукового измерения расстояний аналогичен радиорадару. &lt;/i&gt;&lt;/p&gt;    &lt;p&gt;Разобравшись с принципом действия, я приступил к написанию кода, привлекши на помощь математику и понимая, что до меня этим кто-то обязательно занимался – поиски увенчались успехом, я нашел прекрасный небольшой класс Дж. Вильсона в форумах Netduino &lt;a href="http://forums.netduino.com/index.php?/topic/3256-library-for-hc-sr04-ultrasonic-rangefinder/"&gt;http://forums.netduino.com/index.php?/topic/3256-library-for-hc-sr04-ultrasonic-rangefinder/&lt;/a&gt;&lt;u&gt;.&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;Скачайте этот класс и добавьте к проекту Netduino.&lt;/p&gt;    &lt;p&gt;...&lt;/p&gt;    &lt;p&gt;Создайте проект WP8 так же как и в прошлый раз и добавьте часть по Bluetooth, подобно прошлому проекту. У меня очень простой пользовательский интерфейс. Он состоит из элемента ProgressBar для визуализации уровня громкости, MediaElement для проигрывания песни и TextBlocks для отображения текущих значений.&lt;/p&gt;    &lt;p&gt;Пожалуй, сейчас самое время, чтобы продемонстрировать основы использования MVVM, но я отложу это на будущее. &lt;/p&gt;    &lt;p&gt;Кроме кода Bluetooth, реально только один метод тянет всю работу, и он действительно прост. Этот метод вызывается, когда приходит сообщение от BT. Сообщение в этом случае будет значением расстояния от датчика сонара, выраженное в см.:&lt;/p&gt;    &lt;p&gt;...&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;И, конечно, исходники доступны для обоих проектов…&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10407320" width="1" height="1"&gt;</content><author><name>Russian MSDN</name><uri>http://blogs.msdn.com/Russian-MSDN/ProfileUrlRedirect.ashx</uri></author><category term=".NET Microframework" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/-NET+Microframework/" /><category term="Netduino" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/Netduino/" /><category term="Bluetooth" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/Bluetooth/" /></entry><entry><title>Добавление наглядности в мир WinForm с помощью Visual Drawing.Net</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/rucoding4fun/archive/2013/03/20/adding-some-visual-pizazz-to-your-winform-world-with-visual-drawing-net.aspx" /><id>http://blogs.msdn.com/b/rucoding4fun/archive/2013/03/20/adding-some-visual-pizazz-to-your-winform-world-with-visual-drawing-net.aspx</id><published>2013-03-20T11:36:14Z</published><updated>2013-03-20T11:36:14Z</updated><content type="html">&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://channel9.msdn.com/Niners/gduncan411"&gt;Грэг Дункан&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Этот проект Эрдала Халичи (&lt;a href="http://www.erdalhalici.com/"&gt;Erdal Halici&lt;/a&gt;) откровенно потрясающий. Мы не только получаем замечательный способ конструировать геометрические фигуры для наших приложений, мы можем это делать с помощью навыков Visual Studio, а также получаем исходники этого всего. И да, автор создал прекрасную документацию для всего этого!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.codeproject.com/Articles/545130/Visual-Drawing-Net"&gt;&lt;b&gt;Visual&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;Drawing&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Net&lt;/b&gt;&lt;/a&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;Много лет назад, когда Microsoft только выпустила .NET, я работал программным консультантом и должен был помогать нашим заказчикам начать работать с .NET и ускоренно обучить их новым языкам программирования C# и Visual Basic .NET. Большинство разработчиков, которым я помогал, были разработчиками на Visual Basic 6.0 и многие не были хорошо знакомы с программированием и разработкой OOП-программ. Мне нужен был эффективный путь для объяснения ООП. Поэтому лучшим способом изучения ООП было использование класса Shape, имеющего виртуальный метод Draw, и развитие его с помощью различных аспектов ООП. После этого я также обучал их возможностям конструирования в Visual Studio .NET. После того, как курсы завершились, и все в мире узнали про .NET, у меня остались множество графических образцов; и я думал, как сделать с ними что-то полезное, что могло бы понадобиться и другим. Так я разработал инструментарий разработки графических объектов и среду разработки, интегрируемую с Visual Studio .NET.&lt;/p&gt;    &lt;p&gt;После начала работы программным архитектором для различных компаний в Германии в 2004 году у меня было много ответственной работы, и я полностью забыл об этом инструментарии. Но недавно, просматривая свои файловые архивы, я снова натолкнулся на него. Я обновил его, так что он теперь работает с новыми версиями Visual Studio .NET, включая Visual Studio 2008, 2010 и 2012. Надеюсь, он вам понравится. Он свободно доступен, и его можно скачать вместе с полным исходным кодом с &lt;a href="http://visualdrawingdotnet.codeplex.com/"&gt;http://visualdrawingdotnet.codeplex.com&lt;/a&gt;. Документация доступна на &lt;a href="http://www.erdalhalici.com"&gt;www.erdalhalici.com&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;...&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/2235.clip_5F00_image002_5F00_7D8AF33E.png" width="629" height="418" /&gt;&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/8750.clip_5F00_image004_5F00_3D44B3F7.png" width="571" height="459" /&gt;&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/3750.clip_5F00_image006_5F00_1F73036B.png" width="469" height="459" /&gt;&lt;/p&gt;    &lt;p&gt;&lt;b&gt;Основы&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;Visual Drawing.Net – инструментарий разработки графических фигур в среде, интегрируемой с Visual Studio .NET 2005/2008/2010/20012 и всеми редакциями Express.&lt;/p&gt;    &lt;p&gt;Visual Drawing.Net ускоряет разработку графических приложений, основанных на векторной графике. Все фигуры, созданные с использованием Visual Drawing.Net программируются и их атрибуты и свойства можно менять в любое время работы приложения, их содержащего. Фигуры создаются с помощью парадигмы ООП, поддерживающей визуальное наследование в среде разработки Visual Studio .NET 2005/2008/2010/2012 и всех редакциях Express.&lt;/p&gt;    &lt;p&gt;Visual Drawing.Net имеет богатый набор встроенных фигур, которые разработчики могут перетаскивать на поверхность рисования; также доступны для использования многие средства сторонних фирм. Однако иногда, когда не существует всторенной (или посторонней) фигуры для решения конкретной проблемы, разработчик должен создать собственную с особенным внешним видом или поведением. Созданная однажды настраиваемая фигура становится повторно используемым компонентом, который можно применять в приложениях или скомпилировать в библиотеку фигур для использования в других приложениях. Эта возможность делает Visual Drawing.Net таким мощным средством рисования.&lt;/p&gt;    &lt;p&gt;Разработка фигуры включает в себя создание ее геометрии и задание и реализация поведения. Выбирая правильные комбинации геометрии и поведения, разработчик может создавать фигуры, моделирующие объекты реального мира, которые они представляют. Геометрия фигуры – это ее внешний вид, и состоит из линий, углов, форматирования и способности к поворотам. Также она включает способы структуризации фигуры. Например, состоит ли фигура из простой формы или является контейнером, объединяющим несколько простых форм в одно целое. Вы создаете геометрию фигуры, рисуя ее форму с помощью представления конструирования в Visual Drawing.Net. Также можно создать или расширить геометрию фигуры путем написания кода в представлении кода.&lt;/p&gt;    &lt;p&gt;&lt;b&gt;Почему стоит использовать &lt;/b&gt;&lt;b&gt;Visual&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;Drawing&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Net&lt;/b&gt;&lt;b&gt;?&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;Некоторые причины использования Visual Drawing.Net для разработки фигур:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;Visual Drawing.Net – инструмент для разработчиков, занимающихся конструированием и созданием графических приложений. Он предоставляет настраиваемое рабочее окружение, интегрирующееся с Visual Studio .NET 2003, Visual Studio .NET 2005 и всеми редакциями VS Express и позволяющее задавать, создавать, тестировать и поддерживать фигуры. &lt;/li&gt;      &lt;li&gt;Фигуры являются расширяемыми. Можно создавать собственные фигуры, переписывая метод MakePath и другие методы, создающие фигуры; они могут использоваться в контейнере фигуры. Контейнер фигуры обеспечивает поддержку во время конструирования операций вращения, рассекания, сдвига, деформации, экранирования, заполнения цветом или использования кистей и т. д. &lt;/li&gt;      &lt;li&gt;Visual Drawing.Net обеспечивает согласованность вновь разработанных фигур. Можно реализовывать одно и то же поведение в контейнерах фигур разными способами (например, используя визуальное наследование во всех версиях Visual Studio .NET, включая Express). &lt;/li&gt;      &lt;li&gt;Visual Drawing.Net хранит фигуры в контейнерах, которые также представляют собой объекты Shape, а все атрибуты и поведения ассоциированы с фигурами, которые вы создали независимо, используя языки программирования .NET (C#, VB.Net и т. п.). Это упрощает совместную работу дизайнеров, разработчиков и тестировщиков, или даже управление разными аспектами создания фигур разными командами или компаниями. &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;&lt;b&gt;Когда использовать &lt;/b&gt;&lt;b&gt;Visual&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;Drawing&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;b&gt;Net&lt;/b&gt;&lt;b&gt;?&lt;/b&gt;       &lt;br /&gt;Применяйте Visual Drawing.Net когда захотите совершить одно из следующих действий:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;Создать программируемые фигуры со сложными атрибутами и поведением, такие как фигуры со многими состояниями. &lt;/li&gt;      &lt;li&gt;Создать фигуры, являющиеся частью иерархии подобных фигур или наборов фигур с небольшими отличиями. &lt;/li&gt;      &lt;li&gt;Создавать и обслуживать библиотеки фигур, ��ключая одновременное внесение изменений в ряд фигур. &lt;/li&gt;      &lt;li&gt;Протестировать разработанные фигуры, чтобы удостовериться, что они правильно реализуют заданное поведение. &lt;/li&gt;      &lt;li&gt;Создать фигуры в составе команды разработчиков, разделяя труд дизайнеров, разработчиков и тестировщиков, или отдавая часть процесса разработки третьим фирмам на аутсорсинг. &lt;/li&gt;      &lt;li&gt;Сохранять информацию о фигурах независимо от приложения, в котором они использовались. &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;....&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Статья &lt;a href="http://www.codeproject.com/"&gt;CodeProject&lt;/a&gt; продолжает введение в процесс разработки, добавления фигур и т. д.&lt;/p&gt;  &lt;p&gt;Пример загрузился, скомпилировался и запустился у меня с первого раза безо всяких проблем.&lt;/p&gt;  &lt;p&gt;Вот снимок:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image008" border="0" alt="clip_image008" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/4503.clip_5F00_image008_5F00_47E1BFB2.png" width="629" height="342" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image010" border="0" alt="clip_image010" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/5460.clip_5F00_image010_5F00_16B25F45.png" width="329" height="484" /&gt;&lt;/p&gt;  &lt;p&gt;Мне нравиться иметь примеры сразу на двух языках C# и VB. Прекрасно…&lt;/p&gt;  &lt;p&gt;Я говорил о &lt;a href="http://vddotnet.erdalhalici.com/"&gt;документации&lt;/a&gt;? &lt;/p&gt;  &lt;p&gt;&lt;a href="http://vddotnet.erdalhalici.com/"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image012" border="0" alt="clip_image012" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/6710.clip_5F00_image012_5F00_1350C79D.png" width="629" height="302" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://vddotnet.erdalhalici.com/"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image014" border="0" alt="clip_image014" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/3051.clip_5F00_image014_5F00_5931D4F0.png" width="427" height="1009" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;...&lt;/p&gt;  &lt;p&gt;&lt;a href="http://vddotnet.erdalhalici.com/ShapeContainer.aspx"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image016" border="0" alt="clip_image016" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/7245.clip_5F00_image016_5F00_73621847.png" width="817" height="315" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Я упоминал также обо всех исходных кодах, а не только о примерах CodeProject, которые имеют двоичные файлы для главных компонентов, не так ли?&lt;/p&gt;  &lt;p&gt;Да, просто не в CodePlex...&lt;/p&gt;  &lt;p&gt;&lt;a href="http://visualdrawingdotnet.codeplex.com/"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image018" border="0" alt="clip_image018" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/6366.clip_5F00_image018_5F00_34CCA4D4.png" width="567" height="67" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://visualdrawingdotnet.codeplex.com"&gt;http://visualdrawingdotnet.codeplex.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Вот снимок актуальных компонентов решения (для которых последняя регистрация, так же как и запись о них, компилируются легко и изящно).&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image020" border="0" alt="clip_image020" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/1070.clip_5F00_image020_5F00_2066DF49.png" width="329" height="484" /&gt;&lt;/p&gt;  &lt;p&gt;Итак, снова, вы не только получаете прекрасный проект, но также и все исходники, составляющие его! &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10403847" width="1" height="1"&gt;</content><author><name>Russian MSDN</name><uri>http://blogs.msdn.com/Russian-MSDN/ProfileUrlRedirect.ashx</uri></author><category term="Visual Basic" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/Visual+Basic/" /><category term="C#" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/C_2300_/" /><category term="WinForms" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/WinForms/" /></entry><entry><title>Kegerator + Kegduino + KegMonitor = KegManager!</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/rucoding4fun/archive/2013/03/18/kegerator-kegduino-kegmonitor-kegmanager.aspx" /><id>http://blogs.msdn.com/b/rucoding4fun/archive/2013/03/18/kegerator-kegduino-kegmonitor-kegmanager.aspx</id><published>2013-03-18T12:12:19Z</published><updated>2013-03-18T12:12:19Z</updated><content type="html">&lt;p&gt;&lt;a href="http://channel9.msdn.com/Niners/gduncan411"&gt;Грэг Дункан&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Для сегодняшнего поста я искал чего-то необычного, и, как мне кажется, нашел. Тема слегка устарела, и я не знаю, как ее закончить, и в ней нет аппаратной схемы, но тем не менее, мимо смеси пива, Netduino, Windows 8 ( и твиттера, и распознавания лиц) трудно пройти!&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;a href="http://kegmanager.codeplex.com/"&gt;KegManager&lt;/a&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;&lt;b&gt;Описание&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;проекта&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;KegManager – это программный пакет, спроектированный для сбора, интерпретации и отображения соответствующих данных от кегератора. На каждом уровне проекта используются технологии Microsoft, начиная от .Net Micro Framework и до применения нового имерсивного интерфейса Windows 8.&lt;/p&gt;    &lt;p&gt;&lt;b&gt;&amp;quot;&lt;/b&gt;&lt;b&gt;Kegduino&lt;/b&gt;&lt;b&gt;&amp;quot; – аппаратура&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;Она состоит из аппаратного и программного обеспечения, непосредственно собирающего данные. Все построено вокруг Netduino, работающего с .Net MICRO Framework и соединенного с набором датчиков, собирающих информацию: скорость течения (для разливного пива), температура, давление газа (СО&lt;sub&gt;2&lt;/sub&gt; или N&lt;sub&gt;2&lt;/sub&gt;) и т. п. Эти данные пересылаются по Bluetooth-соединению на ближайший компьютер. &lt;/p&gt;    &lt;p&gt;&lt;b&gt;&amp;quot;KegMonitor&amp;quot; – &lt;/b&gt;&lt;b&gt;журналирование&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;данных&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;Эта программа слушает kegduino, разбирает пакеты и записывает данные для дальнейшего анализа.&lt;/p&gt;    &lt;p&gt;&lt;b&gt;&amp;quot;KegManager&amp;quot; – &lt;/b&gt;&lt;b&gt;отображение&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;Используя новый Windows 8 SDK, имерсивное приложение отображает текущее состояние кегератора, в том числе, какое пиво разливается, текущую температуру, и даже будет поддерживать распознавание лиц потребителей. &lt;/p&gt;    &lt;p&gt;Вот снимок главного проекта в решении...&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/1122.clip_5F00_image002_5F00_4EDF966E.png" width="315" height="484" /&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/4452.clip_5F00_image004_5F00_5D5A9293.png" width="315" height="484" /&gt;&lt;/p&gt;    &lt;p&gt;Диаграмма баз данных;&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/0640.clip_5F00_image006_5F00_1A2F1466.png" width="629" height="375" /&gt;&lt;/p&gt;    &lt;p&gt;Управляющие элементы WPF...&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image008" border="0" alt="clip_image008" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/3782.clip_5F00_image008_5F00_444E9C81.png" width="629" height="288" /&gt;&lt;/p&gt;    &lt;p&gt;И даже KegReader и KegWriters!&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image010" border="0" alt="clip_image010" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/3782.clip_5F00_image010_5F00_05999F1B.png" width="629" height="369" /&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;И как теперь можно сделать что-то не так? По крайней мере, это интересный проект для выпивки &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Улыбка" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/6825.wlEmoticon_2D00_smile_5F00_1D706074.png" /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10403155" width="1" height="1"&gt;</content><author><name>Russian MSDN</name><uri>http://blogs.msdn.com/Russian-MSDN/ProfileUrlRedirect.ashx</uri></author><category term="WPF" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/WPF/" /><category term=".NET Microframework" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/-NET+Microframework/" /><category term="Netduino" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/Netduino/" /></entry><entry><title>Udacity обучает разработке HTML5-игр</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/rucoding4fun/archive/2013/03/18/udacity-teaches-you-html5-game-development.aspx" /><id>http://blogs.msdn.com/b/rucoding4fun/archive/2013/03/18/udacity-teaches-you-html5-game-development.aspx</id><published>2013-03-18T10:16:34Z</published><updated>2013-03-18T10:16:34Z</updated><content type="html">&lt;p&gt;&lt;a href="http://channel9.msdn.com/Niners/gduncan411"&gt;Грэг Дункан&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Я вышел на сегодняшний проект благодаря сообщению Сандира Редди (&lt;a href="http://sandreddy.wordpress.com/2013/02/06/html5-game-development-course/"&gt;Sandeep Reddy&lt;/a&gt;) и хотя это и не то, что планировалось, вы все знаете, как мне нравятся посты, которые «учат ловить рыбу».&lt;/p&gt;  &lt;p&gt;Конечно, учитывая то, где работают эти два инструктора, я мог бы нарваться на неприятности, но слушайте, HTML5 есть HTML5, верно? Разработка игр есть разработка игр, правильно? Все мы счастливы принадлежать к миру HTML5 сейчас, не так ли? Это о коде и обучении; просто человек, а не конкретный человек, вот для кого мы работам! (Так я увольняюсь с этой работы… шутка &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Улыбка" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/0726.wlEmoticon_2D00_smile_5F00_62F888C8.png" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="https://www.udacity.com/"&gt;&lt;b&gt;Udacity&lt;/b&gt;&lt;/a&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;– &lt;/b&gt;&lt;a href="https://www.udacity.com/course/cs255"&gt;&lt;b&gt;разработка игры на &lt;/b&gt;&lt;b&gt;HTML&lt;/b&gt;&lt;b&gt;5&lt;/b&gt;&lt;/a&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;&lt;a href="https://www.udacity.com/course/cs255"&gt;&lt;b&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/0184.clip_5F00_image002_5F00_40006C00.png" width="629" height="299" /&gt;&lt;/b&gt;&lt;/a&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;&lt;b&gt;Обзор урока&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;Этот курс проведет вас через основные этапы построения GRITS – игры на HTML5. Мы расскажем о стандартных приемах разработки игр, и их использовании в создании высокопроизводительных приложений на HTML5.&lt;/p&gt;    &lt;p&gt;&lt;b&gt;Что&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;я&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;должен&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;знать&lt;/b&gt;&lt;b&gt;?&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;Для этого курса необходимы знания HTML, Javascript и как работает веб. Есть дополнительный модуль по отдельным частям Javascript и DOM, который необходимо освежить в памяти для этого курса.&lt;/p&gt;    &lt;p&gt;&lt;b&gt;Что&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;я&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;буду&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;изучать&lt;/b&gt;&lt;b&gt;?&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;После окончания кура вы будете понимать, как разрабатывать HTML5-игры. Вы познакомитесь с такими возможностями HTML5, как 2D-холст, а также с технологией улучшения производительности.&lt;/p&gt;    &lt;p&gt;&lt;b&gt;План&lt;/b&gt;&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;Модуль 0 – Дополнительный интенсивный курс по HTML/Javascript &lt;/li&gt;      &lt;li&gt;Модуль 1 – Введение в рендеринг холста &lt;/li&gt;      &lt;li&gt;Модуль 2 – Рендеринг атласов и карт &lt;/li&gt;      &lt;li&gt;Модуль 3 – Основы ввода, управление событиями &lt;/li&gt;      &lt;li&gt;Модуль 4 – Иерархия сущностей &lt;/li&gt;      &lt;li&gt;Модуль 5 – Box2D и использование внешних библиотек &lt;/li&gt;      &lt;li&gt;Модуль 6 – Добавление звука &lt;/li&gt;      &lt;li&gt;Модуль 7 – Асинхронная загрузка &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;&lt;b&gt;Инструкторы&lt;/b&gt;&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;Колт МакАнлис (Colt McAnlis) &lt;/li&gt;      &lt;li&gt;Питер Либберс (Peter Lubbers) &lt;/li&gt;      &lt;li&gt;Син Беннет (Sean Bennett) &lt;/li&gt;   &lt;/ul&gt; &lt;/blockquote&gt;  &lt;p&gt;Приступайте! Очень интересный курс, свободно доступный на &lt;a href="https://www.udacity.com/"&gt;Udacity&lt;/a&gt;. И начинайте работать над своей следующей клевой HTML5-игрой!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10403141" width="1" height="1"&gt;</content><author><name>Russian MSDN</name><uri>http://blogs.msdn.com/Russian-MSDN/ProfileUrlRedirect.ashx</uri></author><category term="GameDev" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/GameDev/" /><category term="HTML5" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/HTML5/" /></entry><entry><title>Интернет вещей… таких, как газовый сенсор Gadgeteer с ThingSpeak</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/rucoding4fun/archive/2013/03/15/internet-of-things-such-as-a-gadgeteer-gas-sensor-with-thingspeak.aspx" /><id>http://blogs.msdn.com/b/rucoding4fun/archive/2013/03/15/internet-of-things-such-as-a-gadgeteer-gas-sensor-with-thingspeak.aspx</id><published>2013-03-15T08:28:11Z</published><updated>2013-03-15T08:28:11Z</updated><content type="html">&lt;p&gt;&lt;a href="http://channel9.msdn.com/Niners/gduncan411"&gt;Грэг Дункан&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Сегодняшний проект слегка отличается от других (я знаю, что каждый раз так говорю, но опять же, я стараюсь сделать каждый пост о чем-то слегка отличном…) и, как мне кажется, довольно интересен. Мне нравится, как в нем слились две технологии, а также здесь использована библиотека, о которой мы недавно говорили, «&lt;a href="http://blogs.msdn.com/b/rucoding4fun/archive/2013/01/17/get-your-net-micro-framework-devices-up-with-the-plibrary.aspx"&gt;Усильте свои устройства на .Net Micro Framework с помощью μPLibrary!&lt;/a&gt;»&lt;/p&gt;  &lt;p&gt;Отдадим должное, я нашел этот пост на сайте &lt;a href="http://hackaday.com/"&gt;Hack A Day's&lt;/a&gt;, «&lt;a href="http://hackaday.com/2013/01/31/gas-sensor-suite-built-with-gadgeteer-modules/"&gt;Gas sensor suite built with Gadgeteer modules&lt;/a&gt;».&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=ro2Wd1ciEpY"&gt;&lt;b&gt;Газовый сенсор на &lt;/b&gt;&lt;b&gt;Gadgeteer&lt;/b&gt;&lt;b&gt; с &lt;/b&gt;&lt;b&gt;ThingSpeak&lt;/b&gt;&lt;/a&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;Демонстрация газового сенсора на Gadgeteer Gas Sensor использует ThingSpeak. Канал ThingSpeak для этого проекта доступен по адресу &lt;a href="https://thingspeak.com/channels/3512"&gt;https://thingspeak.com/channels/3512&lt;/a&gt;, хотя я проверял различные газовые сенсоры. Хочу поблагодарить Паоло за его превосходные библиотеки ThingSpeak, которые я получил из его проекта на CodePlex «μPLibrary - Net Micro Framework Helper Library», доступного по адресу &lt;a href="http://uplibrary.codeplex.com/"&gt;http://uplibrary.codeplex.com/&lt;/a&gt;. Исходный код этого проекта сейчас доступен по ссылке &lt;a href="http://www.tinyclr.com/codeshare/entry/607"&gt;http://www.tinyclr.com/codeshare/entry/607&lt;/a&gt;. Сайт Gadgeteer Framework – &lt;a href="http://gadgeteer.codeplex.com"&gt;http://gadgeteer.codeplex.com&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/ro2Wd1ciEpY&amp;amp;hl=en"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/ro2Wd1ciEpY&amp;amp;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://www.tinyclr.com/codeshare/entry/607"&gt;Gadgeteer Gas Sensors and ThingSpeak&lt;/a&gt;&lt;/p&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;Демонстрация как использовать ThingSpeak (веб-сайт интернета вещей – IOT ) с газовым сенсором Gadgeteer. Данные сенсоров выдаются в реальном времени на ThingSpeak, а используя возможности ThingSpeak, сенсор может посылать твиты в случае возникновения сигнала тревоги.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="https://thingspeak.com/channels/3512"&gt;https://thingspeak.com/channels/3512&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="https://thingspeak.com/channels/3512"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/7701.clip_5F00_image002_5F00_32825621.png" width="249" height="459" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;И, как упоминалось, исходный код проекта доступен!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.tinyclr.com/codeshare/entry/607"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/3175.clip_5F00_image004_5F00_1C6BC4C2.png" width="291" height="480" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;С помощью .Net Gadgeteer, нескольких деталей, нескольких библиотек, технологии «подсоедини и работай» и собственной креативности вы получите собственные замечательные вещи…&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10402563" width="1" height="1"&gt;</content><author><name>Russian MSDN</name><uri>http://blogs.msdn.com/Russian-MSDN/ProfileUrlRedirect.ashx</uri></author><category term=".NET Microframework" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/-NET+Microframework/" /><category term=".NET Gadgeteer" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/-NET+Gadgeteer/" /></entry><entry><title>Fall Fury, PDF-файл!</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/rucoding4fun/archive/2013/03/13/fall-fury-the-pdf.aspx" /><id>http://blogs.msdn.com/b/rucoding4fun/archive/2013/03/13/fall-fury-the-pdf.aspx</id><published>2013-03-13T15:46:29Z</published><updated>2013-03-13T15:46:29Z</updated><content type="html">&lt;p&gt;&lt;a href="http://channel9.msdn.com/Niners/gduncan411"&gt;Грэг Дункан&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Вы все видели последние статьи Coding4Fun по проекту Fall Fury, верно?&lt;/p&gt;  &lt;p&gt;Что? Нет? (Конечно, я знаю, что ВЫ видели, но может кто-то другой не видел…)&lt;/p&gt;  &lt;p&gt;В любом случае, что такое Fall Fury?&lt;/p&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;FallFury это 2D платформер в котором игрок управляет падающим медведем, стараясь избежать препятствий, увертываясь от ракет и уничтожая монстров по мере падения. В проект включены несколько несколько новых API Windows 8, включая акселерометр и касания, а также интеграцию с функциями ядра ОС, такими как настройки и разделение параметров. Кроме того, проект реализует наиболее требовательные добавления к среде разработки Visual Studio – разработке гибридных приложений с помощью XAML, C++ и DirectX.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Вот содержание всей серии:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-1-Introduction"&gt;Fall Fury: Часть 1 – Введение&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-2-Shaders"&gt;Fall Fury: Часть 2 – Шейдеры&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-3-Basic-Rendering-and-Movement"&gt;Fall Fury: Часть 3 – Основы рендеринга и движений&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-4-XAML-Interop"&gt;Fall Fury: Часть 4 – Взаимодействие с XAML&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-5-Creating-Levels"&gt;Fall Fury: Часть 5 – Создание уровней&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-6-Rendering-Level-Elements"&gt;Fall Fury: Часть 6 – Рендеринг элементов уровней&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-7-Animations"&gt;Fall Fury: Часть 7 – Анимация&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-8-Element-Interaction"&gt;Fall Fury: Часть 8 – Взаимодействие элементов&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-9-Particle-System"&gt;Fall Fury: Часть 9 – Система частиц&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-10-Charms"&gt;Fall Fury: Часть 10 – Чудо-кнопки&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-11-Hardware-Testing--Debugging"&gt;Fall Fury: Часть 11 – Тестирование аппаратуры и отладка&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-12-Conclusions"&gt;Fall Fury: Часть 12 – Заключение&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Он содержит видео, пояснения к коду, загружаемые файлы, все вместе…&lt;/p&gt;  &lt;p&gt;Но с 12 постами сложно работать, особенно если вы хотите иметь печатный вариант для чтения офлайн. Было бы здорово, если бы всё содержимое было доступно в одном pdf-файле? &lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf"&gt;Fall Fury, PDF&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/6012.clip_5F00_image002_5F00_5B0CA665.png" width="350" height="459" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Правильно! В��я серия из 12 постов доступна в отформатированном 131-страничном PDF-файле! &lt;/p&gt;  &lt;p&gt;Загружайте и получайте своего медвежонка! &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10402011" width="1" height="1"&gt;</content><author><name>Russian MSDN</name><uri>http://blogs.msdn.com/Russian-MSDN/ProfileUrlRedirect.ashx</uri></author><category term="DirectX" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/DirectX/" /><category term="XAML" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/XAML/" /><category term="C++" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/C_2B002B00_/" /></entry><entry><title>Пример приложения Windows Store DirectX C++</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/rucoding4fun/archive/2013/03/13/windows-store-directx-c-sample.aspx" /><id>http://blogs.msdn.com/b/rucoding4fun/archive/2013/03/13/windows-store-directx-c-sample.aspx</id><published>2013-03-13T08:02:40Z</published><updated>2013-03-13T08:02:40Z</updated><content type="html">&lt;p&gt;&lt;a href="http://channel9.msdn.com/Niners/gduncan411"&gt;Грэг Дункан&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Сегодняшний проект Михаэла МасЛауга (Michael B. McLaughlin) привел в восхищение команду Channel 9, был удостоен звания «Герой недели» передачи «&lt;a href="http://channel9.msdn.com/Shows/This+Week+On+Channel+9/TWC9-February-01-2013"&gt;Неделя на Channel 9&lt;/a&gt;» и прислан мне со словами: “Привет Грэг, не мог бы ты…” другим сотрудником канала.&lt;/p&gt;  &lt;p&gt;В прошлом июне (ух, это было так давно!) мы рассказывали о наборе инструментов DirectX Toolkit, &lt;a href="http://channel9.msdn.com/coding4fun/blog/DirectXTK-the-DirectX-Tool-Kit"&gt;DirectXTK – the DirectX Tool Kit&lt;/a&gt; (этот проект можно найти по ссылке &lt;a href="http://directxtk.codeplex.com/"&gt;http://directxtk.codeplex.com/&lt;/a&gt;). Сегодняшний проект использует DirectXTK и демонстрирует, как ввести его в мир Windows App Store…&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geekswithblogs.net/mikebmcl/archive/2013/01/31/windows-store-directx-c-sample-base.aspx"&gt;&lt;b&gt;База примеров Windows Store DirectX C++ &lt;/b&gt;&lt;/a&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;Я работал над ней с перерывами на протяжении года (по существу полностью переписав во второй половине прошлого года). Наконец он завершен. Я предоставлю вам базу примеров Windows Store DirectX C++. На их основе можно создать игру. Она прошла тестирование WACK (Windows App Certification Kit) и правильно работает на моем Surface RT и других компьютерах x64. Она обрабатывает вращения. Позволяет выбрать фиксированный размер заднего буфера (back buffer). Включает класс аудиодвижка, класс Texture2D и класс RenderTarget2D. Использует &lt;a href="http://directxtk.codeplex.com/"&gt;DirectXTK&lt;/a&gt;. Позволяет делать причудливые вещи вроде смешивания XAML и DirectX при использовании множественной дискретизации. Имеет настраиваемую панель с предустановленными регуляторами громкости, панель настройки уровня безопасности (от вас требуется предоставить соответствующие политики безопасности и иные необходимые элементы управления, если они есть) и даже настройки панели «about». Демонстрирует основы использования XInput. Показывает основы выполнения асинхронной обработки событий на С++ используя библиотеку ConcRT PPL Tasks. И даже включает кота Шона Харгрейвса (Shawn Hargreaves) и васильковый фон. &lt;/p&gt;    &lt;p&gt;…Код обильно откомментирован. Следует обратить внимание на файлы App.xaml.cpp, DirectXPage.xaml.cpp, DirectXPage.xaml и Game.cpp (которые получены из DirectXBase, на которую вы, возможно также захотите взглянуть). Отметим, что описания всех функций даны в файлах заготовков (*.h), а комментарии того, как они это делают, обычно размещены в CPP-файлах. &lt;/p&gt;    &lt;p&gt;Вы можете использовать пример отсюда: BaseWin8Direct3DApp.zip [ГД. Перейдите на &lt;a href="http://geekswithblogs.net/mikebmcl/archive/2013/01/31/windows-store-directx-c-sample-base.aspx"&gt;исходный пост&lt;/a&gt; и получите ссылку там. Я вовсе не хочу перехватывать его трафик…] Вам нужна Windows 8 и Visual Studio Express 2012 для Windows 8 или Visual Studio 2012 Professional или еще более старшая. Я надеюсь начать создание примеров с их использованием в качестве основы совсем скоро. Меня волновало, когда другие делали то же самое. Также я постараюсь включить некоторые сообщения об общих темах разработки для Windows Store (полезные ссылки, интересные блоги, и т. п.) и об использовании C++.&lt;/p&gt;    &lt;p&gt;...&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Не хотите усовершенствоваться в С++? Михаэл и SyncFusion предоставляют такую возможность в свободно доступной электронной книге «&lt;a href="http://geekswithblogs.net/mikebmcl/archive/2012/09/07/c-succinctly-now-available.aspx"&gt;Сжато о С++&lt;/a&gt;».&lt;/p&gt;  &lt;p&gt;Примеры кода были загружены, откомпилированы и запущены мною с первого раза. Это простой пример, но он так и задуман, чтобы предоставить возможность войти и начать работать в мире DirectX Windows 8.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/5482.image_5F00_7AC21622.png" width="500" height="281" /&gt;&lt;/p&gt;  &lt;p&gt;Кроме того стандарты блога требуют ото всех публикации на протяжении года хотя бы одного изображения кота, которое мы выполнили в 2013-ом …&lt;/p&gt;  &lt;p&gt;В любом случае...&lt;/p&gt;  &lt;p&gt;Вот снимок решения:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/6866.image_5F00_581DD7A7.png" width="300" height="364" /&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/2251.image_5F00_7BF68934.png" width="300" height="298" /&gt;&lt;/p&gt;  &lt;p&gt;Как видно, тут больше, чем может охватить глаз, больше, чем вы видите в примере, много больше, чем показать кота (в этом нет ничего плохого… )&lt;/p&gt;  &lt;p&gt;Если вы хотите начать работать с DirectX в приложениях Windows Store App, этот пример, похоже, хорошее место для старта…&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10401880" width="1" height="1"&gt;</content><author><name>Russian MSDN</name><uri>http://blogs.msdn.com/Russian-MSDN/ProfileUrlRedirect.ashx</uri></author><category term="DirectX" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/DirectX/" /><category term="C++" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/C_2B002B00_/" /><category term="Windows Store Applications" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/Windows+Store+Applications/" /></entry><entry><title>Windows Phone 8, Netduino и Bluetooth...</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/rucoding4fun/archive/2013/02/27/windows-phone-8-netduino-and-bluetooth.aspx" /><id>http://blogs.msdn.com/b/rucoding4fun/archive/2013/02/27/windows-phone-8-netduino-and-bluetooth.aspx</id><published>2013-02-27T08:44:46Z</published><updated>2013-02-27T08:44:46Z</updated><content type="html">&lt;p&gt;&lt;a href="http://channel9.msdn.com/Niners/gduncan411"&gt;Грэг Дункан&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Сегодняшний проект пришел к нам от Мэта Каванага (Matt Cavanagh) и посвящен…&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;a href="http://blog.roguecode.co.za/Post/ControllingaNetduinooverBluetoothwithWP8"&gt;Управление Netduino с WP8 через Bluetooth&lt;/a&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;В последний раз я дотрагивался до моего Netduino пять месяцев назад (из-за загрузки на работе) примерно с того момента, как женился. Поэтому в эти выходные я решил стряхнуть с него пыль и познакомить со своим Lumia 920. &lt;/p&gt;    &lt;p&gt;Разъяснение: На самом деле я не стряхивал с него пыль.&lt;/p&gt;    &lt;p&gt;Теперь они друзья.&lt;/p&gt;    &lt;p&gt;Вот видео того, чему посвящен пост, для объяснения, как это работает. Трудно увидеть реальные цвета вещей на видео – так что поверьте мне на слово, что всё работает.&lt;/p&gt;    &lt;p&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/m6WNIbC502I&amp;amp;hl=en"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/m6WNIbC502I&amp;amp;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;    &lt;p&gt;Я собираюсь начать с объяснения части, связанной с Netduino, а затем перейду к WP8. Я постараюсь максимально доходчиво объяснить предмет, на случай, если кто-то на планете хуже меня разбирается в электронике… &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Сначала займемся аппаратурой…&lt;/p&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;Сначала надо обновить Netduino. Удивительно, но Netduino не обновляет себя, сидя в чулане. Я работаю с Windows 8, ио так как по ошибке прописал его ROM файлом Netduino Plus, все драйверы работали прекрасно и ничего специально делать не пришлось. &lt;/p&gt;    &lt;p&gt;Затем я прицепил замечательный компактный Bluetooth-модуль компании Pro-tecc:&lt;/p&gt;    &lt;p&gt;...&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/5148.clip_5F00_image002_5F00_016BEDD5.png" width="629" height="343" /&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;... далее Windows Phone 8&lt;/p&gt;  &lt;blockquote style="background-color: #f6f5e9"&gt;   &lt;p&gt;Windows Phone 8.&lt;/p&gt;    &lt;p&gt;Создайте новое приложение WP8 в VS2012. Да, это возможно лишь в WP8, не в 7.&lt;/p&gt;    &lt;p&gt;Я создал простой интерфейс с тремя слайдерами, по одному на каждый цвет. По умолчанию, цвет слайдеров с левой стороны будет основным цветом телефона, так что я отменил этот стиль и заменил его. Ниже располагается прямоугольник, залитый выбранным цветом. Ниже идут три зависимых кнопки: Still (спокойный), Strobe (стробируемый), и Ambient (внешний). Кнопка Still просто посылает величины, выбранные с помощью слайдеров. Strobe посылает каждые 100 мс случайные величины (существенно мигая светодиодом). Действие кнопки Ambient немного сложнее. Я использовал заднюю камеру устройства для получения среднего цвета поверхности, на которую смотрит телефон, а затем отсылал его Netduino. Чтобы заставить камеру инициалироваться мне пришлось поместить скрытый прямоугольник в UI и привязать его кисть к камере.&lt;/p&gt;    &lt;p&gt;Поверх этого располагается элемент Grid с градусником, демонстрирующим соединение. Если соединения не происходит (или соединение проходит в первый раз), этот элемент будет показываться поверх всей картинки до тех пор, пока произойдет успешное соединение и не буде получен тестовый пинг.&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/2821.clip_5F00_image004_5F00_7CC5BD4D.png" width="279" height="459" /&gt;&lt;/p&gt;    &lt;p&gt;...&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-10-39-metablogapi/0250.clip_5F00_image006_5F00_0CF18547.png" width="624" height="459" /&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Исходники? Да, он предоставил исходный код для обеих сторон, &lt;a href="http://blog.roguecode.co.za/Post/ControllingaNetduinooverBluetoothwithWP8"&gt;достаточно щелкнуть на посте&lt;/a&gt; и промотать текст до конца сообщения. &lt;/p&gt;  &lt;p&gt;Это поможет вам начать работу и предохранить WP8 от грусти…&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10397491" width="1" height="1"&gt;</content><author><name>Russian MSDN</name><uri>http://blogs.msdn.com/Russian-MSDN/ProfileUrlRedirect.ashx</uri></author><category term=".NET Microframework" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/-NET+Microframework/" /><category term="Windows Phone 8" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/Windows+Phone+8/" /><category term="Bluetooth" scheme="http://blogs.msdn.com/b/rucoding4fun/archive/tags/Bluetooth/" /></entry></feed>