воскресенье, 27 октября 2013 г.

Асинхронная загрузка данных с индикацией

Я как-то уже затрагивал тему асинхронной загрузки данных в своей статье TaskExtensions в помощь. Однако, используя такой подход, код со временем начинал обрастать огромным количеством callback'ов и командами. Чтобы оптимизировать данный процесс для своих нужд я сделал класс, которым и хочу поделиться. Ничего нового в нем нет, однако, он позволил сократить огромное количество кода и на мой взгляд является весьма интересным.
Суть класса такова: предоставить пользователю коллекцию динамических данных с выдачей уведомлений при обновлении, а также обеспечить механизм индикации загрузки данных, при этом выбор источника данных предоставить потребителю.
Самый классический сценарий для UI-девелопера: список объектов и кнопка "Обновить". Я решил совместить это в одной коллекции:

public sealed class AsyncObservableCollection<T> : ObservableCollection<T>, ICommand
{
    private readonly Func<Object, Task<IEnumerable<T>>> factory;

    public AsyncObservableCollection(Func<Object, Task<IEnumerable<T>>> factory)
    {
        this.factory = factory;
    }
}

четверг, 26 сентября 2013 г.

Совершенный код



Если бы я прочитал эту книгу года 3-4 назад, мне бы она показалась гораздо интересней...
Автор очень подробно описывает организацию кода (занимает первую половину книги), поэтому для тех, у кого с этим проблемы - это просто кладезь знаний. Вторая часть книги, которая посвящена усовершенствованию кода и конструированию, для меня оказалась более интересной. Поражает такое количество источников, из которых автор черпал материал для своей книги. Во многих главах приводятся результаты различных исследований в области разработки ПО, и хотя некоторые из них устарели, они все равно очень интересны и порой удивляют.

четверг, 29 августа 2013 г.

Атлас Москвы

Приложение "Атлас Москвы" предоставляет легкий и удобный доступ к открытым данным портала правительства Москвы. Эти данные представляют интерес не только для самих государственных органов и не только для целей государственного управления, но и для граждан, бизнес-сообщества, научных, социальных, образовательных институтов, гражданских активистов.





















четверг, 25 июля 2013 г.

Barley-Break Update!

Сегодня обновил дизайн своего первого приложения в Windows Store - Barley-Break. Вроде неплохо получилось! :)


Сохранение настроек приложения в изолированном хранилище

По поводу хранения настроек приложения написано уже очень много статей. Но о том, что сохранять свои данные можно так же в изолированном хранилище - очень мало упоминаний. Я не буду рассказывать о том, что это такое (об этом очень хорошо написано на MSDN), я просто хочу предложить некоторое решение, которое позволит вам хранить свои данные без особых усилий.

Что из себя представляют настройки приложения? Это коллекция пар ключ/значение. То есть это некоторый IDictionary<TKey, TValue>, где в качестве ключа выступает, как правило, строковый параметр, а в качестве значения, в идеале, может быть любой объект. Если внимательно посмотреть на пространство имен System.IO.IsolatedStorage, то можно обнаружить, что класс с таким функционалом уже есть - это IsolatedStorageSettings. Однако он доступен только для Silverlight и Silverlight for Windows Phone. А для настольных приложений доступен только класс IsolatedStorageFile, который представляет область изолированного хранения, содержащую файлы и папки. То есть разработчики настольных приложений здесь несколько обделены функционалом. Собственно этот пробел я и решил заполнить.

Идея до безобразия проста: ключ - это файл в изолированном хранилище, в котором хранится значение этого ключа в виде сериализованных двоичных данных. Однако, если ключ будет состоять из символов, которые не могут содержаться в имени файла (\/:*?"<>|), возникает проблема. Решение, в принципе, такое же простое - хранить значения оригинальных ключей в отдельном служебном файле и каждому такому значению сопоставлять уникальный идентификатор, по имени которого будет создаваться файл для хранения значения оригинального ключа. Если не совсем понятно, то надеюсь рисунок все прояснит:

(info.dat - служебный файл, Key - оригинальный ключ, Guid - уникальный идентификатор)

понедельник, 1 июля 2013 г.

Мифический человеко-месяц


На днях закончил чтение книги Фредерика Брукса "Мифический человеко-месяц". Не смотря на то, что первое издание книги было выпущено в 1975 году, а второе (которое я собственно и читал) - в 1995 году и даже учитывая тот факт, что некоторые главы книги окончательно устарели, тем не менее этот бестселлер просто напичкан фразами, которые актуальны и по сей день. Конечно, эта книга уже давно разошлась на цитаты, но я позволил себе выписать те, которые понравились лично мне.

четверг, 30 мая 2013 г.

Локализованный BooleanToStringConverter.

Для разработчиков пользовательских интерфейсов актуальна задача отображения значения типа Boolean в виде локализованной строки. Т.е. вместо "True" и "False" требуется отобразить "Да" и "Нет" (естественно в зависимости от языка ОС). В связи с этим, хочу предложить интересное решение.
Для начала следует определиться, откуда получить локализованное значение типа Boolean в человеческом виде? Для этого используем библиотеку "User32.dll", которая и вернет нам эти данные.


Как видно на скриншоте, под идентификаторами 805 и 806 имеются строки "&Да" и "&Нет" соответственно. Вот их и будем использовать.

среда, 22 мая 2013 г.

Windows Store. Приложение Fisheye.

Хочу представить свое новое приложение для магазина Windows Store - Fisheye. Оно позволяет просматривать WEB-камеры по всему миру. Также есть возможность добавлять новые камеры на карту.


На текущий момент функционал приложения достаточно простой, но есть много идей по развитию данного направления. Так что, в зависимости от свободного времени, буду развивать и добавлять новый функционал и новые WEB-камеры.

Если есть пожелания - буду очень рад выслушать.
Спасибо!

вторник, 14 мая 2013 г.

Windows Store App. Подключение шрифта.

Несмотря на руководство по шрифтам для приложений магазина Windows, которое рекомендует использовать Segoe UI шрифт для элементов пользовательского интерфейса, иногда может возникнуть потребность подключить дополнительный шрифт. Однако этот шрифт может отсутствовать на клиентском компьютере и соответственно будет использоваться шрифт по умолчанию. Далее я опишу как можно внедрить шрифт в приложение Windows Store  на примере 3D LET.
Для этого скопируем файл шрифта (в данном случае 3dlet.ttf) в папку Assets и добавим его в проект. Установим свойство Build Action = Content и Copy to Output Directory = Do not copy. Тем самым наш новый шрифт будет распространяться вместе с приложением.
Теперь, чтобы использовать этот шрифт, потребуется правильно указать свойство FontFamily объекта TextBlock ( FontFamily = "{TTF File Name}#{Font Name}" ):

MainPage.xaml:
    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock Grid.Row="1" Text="3D LET BRK FONT" FontFamily="Assets/3dlet.ttf#3D LET BRK" FontSize="64" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>

При этом текстовый блок примет новый вид:


среда, 24 апреля 2013 г.

Bing Maps. Стилизация Pushpin.

В этой статье я продолжу обзор использования Bing Maps в приложениях Windows Store. Но на этот раз я расскажу как стилизовать Pushpin-объекты на карте для различных типов объектов. Сразу приведу результат программы, чтобы было понятнее о чем идет речь.




Как видно, на карте расположено несколько объектов различного типа (магазины, кинотеатры, POI). Все эти объекты находятся в одной коллекции MapItemsControl объекта Map.

суббота, 13 апреля 2013 г.

Bing Maps в приложениях Windows Store.

Если вы разрабатываете приложение, которое используют геолокацию - без карт вам не обойтись. В данном посте я расскажу как внедрить карты в свое Windows Store приложение на примере Bing Maps.

Первым делом нужно создать Bing Maps Account (можно использовать свою учетную запись Microsoft). Для того, чтобы использовать карты в своем приложении потребуется также создать Bing Map Key (в разделе Create or view keys), который используется для проверки подлинности карты. На данный момент существует три типа ключей:
  • Trial (используется в течение 90-дневного периода, при этом количество транзакций не должно превышать 10 000 за любой 30-дневный срок);
  • Basic (не имеет периода использования, однако количество транзакций не должно превышать 50 000 за 24 часа.);
  • Enterprise (используется для корпоративных учетных записей).
В таблице ниже приведены примеры, когда и какой ключ можно использовать:

Trial key Basic key Enterprise key
Public website + + +
Private website + - +
Mobile + + +
Windows Store app + + +
Business asset managment + - +
Education + + -
Not-for-profit + + -

После того как нужный ключ создан - следует установить Bing Maps SDK for Windows Store apps. Теперь все готово - перейдем непосредственно к приложению.

понедельник, 8 апреля 2013 г.

Azure Mobile Service - Как получить все данные?

Разбираясь с Windows Azure Mobile Service, наткнулся на очень интересный нюанс: при запросе данных с помощью метода IMobileServiceTable<T>.ToListAsync (и других аналогичных методов соответствующего интерфейса) количество возвращаемых записей (по умолчанию) не превышает 50! (Более подробно можно прочитать здесь).

Example:
    var mobileServiceTable = App.MobileService.GetTable<SomeObject>();
    var cloudList = await mobileServiceTable.OrderBy(obj => obj.SomeProperty).ToListAsync();
    var count = 0;
    foreach (var item in cloudList)
    {
        count++;
    }
    Debug.WriteLine(count);
Если кол-во объектов SomeObject > 50, count все равно будет равен 50

То есть для того, чтобы получить 150 записей, нужно использовать метод IMobileServiceTable<T>.Take и непосредственно указывать нужное количество. А если это количество заранее не известно? К примеру, нужно синхронизировать базу данных в облаке с локальной копией.
Чтобы узнать общее количество записей, потребуется интерфейс ITotalCountProvider, используя который можно получить количество всех записей, возвращаемых запросом.

Example:
    var mobileServiceTable = App.MobileService.GetTable<SomeObject>();
    var cloudList = await mobileServiceTable.OrderBy(obj => obj.SomeProperty).IncludeTotalCount().ToListAsync();
    var countProvider = cloudList as ITotalCountProvider;
    Debug.WriteLine(countProvider.TotalCount);
    var count = 0;
    foreach (var item in cloudList)
    {
        count++;
    }
    Debug.WriteLine(count);

Однако, это не решает проблему, так как переменная count будет по прежнему равно 50 (хотя TotalCount = 150).

суббота, 30 марта 2013 г.

Создание мобильной службы в Windows Azure

В продолжение знакомства с Windows Azure я расскажу как можно легко создать мобильную службу в облаке. Чтобы выполнить данный пример потребуется:

  1. Наличие подписки на Windows Azure (можно бесплатное пробное использование);
  2. Установленный пакет Mobile Services SDK.
Процесс создания службы достаточно прост. Для этого, в панели управления Windows Azure , следует зайти в раздел "Мобильные службы" и выбрать пункт "Создать".






Указываем имя мобильной службы (в конечном варианте оно будет следующим: https://{You Name}.azure-mobile.net), экземпляр базы данных, в которой будут хранится данные (если база данных не создана, то ее потребуется создать) и регион, где будет располагаться служба. Важно отметить, что регион сервера базы данных и регион мобильной службы должны совпадать, иначе вы будете платить за лишний трафик.

пятница, 22 марта 2013 г.

Протокол Windows Store (ms-windows-store)

Помимо возможности извне открывать страницу "Отзывы и оценки" приложения в магазине Windows (описание см. в статье Windows Store. Rate and Review), существует ряд других возможностей по работе с протоколом магазина.
К примеру, чтобы вызвать страницу описания приложения достаточно выполнить следующее действие:
ms-windows-store:PDP?PFN=package_family_name, где в качестве параметра принимается - это PackageId.FamilyName.
Так же существует возможность открыть страницу обновления магазина Windows:
Ну и можно выполнить поиск по магазину:
ms-windows-store:Search?query=Bessonov Kirill, где в качестве параметра принимается поисковый запрос.
Для более удобной работы с данным функционалом, объединим это во вспомогательный класс:

вторник, 19 марта 2013 г.

Конкурс «Добавь праздник в Windows Store»



Завершился конкурс приложений для Windows 8, в котором участвовало 54 кандидата. При оценке приложений данные брались из российского Windows Store по TOP FREE/PAID, а также учитывалось количество оценок и средний рейтинг.

В номинации "Самое популярное приложение за время конкурса" победило мое приложение Конвертер валют! :)

Хотел выразить благодарность организаторам конкурса и всем, кто голосовал за мое приложение.
Спасибо!

воскресенье, 17 марта 2013 г.

WIX + SQL Server

Для работы многих приложений требуется база данных. Это не проблема, если база одна на всех и находится на общедоступном сервере. Но как быть если требуется установить базу данных локально? Наилучшим вариантом в этом случае будет создание базы данных во время установки приложения. В этой статье я опишу как, используя WIX, можно во время установки приложения проверить подключение к Sql Server и выполнить скрипт для создания базы данных.

Предварительные условия:

  1. Наличие Visual Studio;
  2. Установленный компонент WIX Toolset.
В качестве шаблона проекта я использую пример из статьи WIX + NET 4.0 Framework + Microsoft Windows Installer 3.1.
Для того, чтобы пользователь смог настроить подключение к серверу баз данных, ему нужно предоставить пользовательский интерфейс, где он сможет ввести нужные учетные данные.

воскресенье, 10 марта 2013 г.

Создание WCF службы в Windows Azure

Посетив Windows Azure Summit, я решил поближе познакомиться c "лазурными облаками". Было принято решение начать с размещения WCF-службы в облаке, о чем речь и пойдет в этом посте.
Прежде чем начать разработку, следует соблюсти ряд условий. А именно:
  1. Наличие подписки на Windows Azure (можно бесплатное пробное использование);
  2. Установленный инструмент Windows Azure SDK.
После того, как все готово для разработки, запускаем Visual Studio и создаем проект "Windows Azure Cloud Service", как показано на рисунке:



Затем выбираем веб-роль служб WCF:

четверг, 28 февраля 2013 г.

Windows Store. Popup AppBar Button

На сайте MSDN есть статья How to add a menu to an app bar, в которой рассказывается как сделать дополнительное меню в AppBar приложения для магазина Windows. Я решил немного улучшить данный вариант и сделал элемент управления, который автоматически показывал бы всплывающее меню с нужным мне контентом.
Собственно что из этого получилось я покажу на скриншоте и уже потом немного опишу весь процесс.


понедельник, 18 февраля 2013 г.

Windows Store. Rate and Review

Каждому разработчику интересно, что думают пользователи о его программе, сервисе, сайте... Что устраивает, чего не хватает, что раздражает? Магазин Windows предоставляет возможность пользователям оценить и оставить отзыв о приложении. Вещь замечательная, но далеко не каждый пользователь использует эту возможность (а некоторые возможно и не знают). А ведь это может помочь рзработчикам улучшить свой продукт, исправить ошибки, да и вообще понять, что работаешь не зря! :) Поэтому, исключительно для блага, можно подтолкнуть пользователя на столь ответственный шаг. И лучше всего это сделать ненавязчиво, с минимальными затратами "пользовательских ресурсов".

Как же открыть страницу "Отзывы и оценки" в Windows Store из приложения? Это достаточно просто:

Code:
Launcher.LaunchUriAsync(new Uri(String.Concat("ms-windows-store:REVIEW?PFN=", Package.Current.Id.FamilyName)))

Где Package.Current.Id.FamilyName - это имя семейства пакета (Package family name), которое можно найти в манифесте приложения на вкладке Packaging.

четверг, 14 февраля 2013 г.

Windows 8 Store. Локализация приложения.

С каждым днем в магазине Windows появляется все больше и больше приложений. Есть хорошие приложения и плохие, есть приложения на нашем родном языке, а есть на "китайском", при чем не понятно что они делают в Российском Windows Store и на какую аудиторию расчитаны. Конечно же такие приложения - это антипример и уж если вы распространяете приложение во всех странах (помимо своей Родины), то постарайтесь сделать  локализацию  хоят бы на анлийском языке. Отличный пример такого приложения: 
Разрабатывая свое второе приложение для Windows Store я задался целью сделать подобную локализацию, и хоть столкнулся с некоторыми трудностями, но в итоге это у меня получилось:


суббота, 2 февраля 2013 г.

Windows 8 FlipControl


Стандартный элемент управления FlipControl (от слова flip - переворачивать) имеет переднюю и заднюю часть для содержания контента и может переворачиваться от одного вида к другому. Как правило реализация подобного элемента управления сводится к созданию 2-х свойств зависимостей: FronContent и BackContent. И соответственно в качестве контента устанавливается нужный вам элемент. Я же решил пойти дальше и не ограничивать себя количеством элементов, которые может содержать FlipControl. Вот что получилось:


вторник, 29 января 2013 г.

Путь джедая...

С середины 2012 года Microsoft обновила свою программу сертификации. Теперь система статусов выглядит более понятной.
Предлагаю вашему вниманию сводную талицу по всем доступным сертификациям. Выберите свой путь к успеху!


пятница, 18 января 2013 г.

Task Extensions в помощь

При разработке пользовательского интерфейса очень часто возникают ситуации, когда требуется получить некторые данные из различных источников (база данных, web-сервис, wcf-сервис и т.д.). При этом хорошим тоном будет отображать пользователю, что приложение выполняет запрос, а не "вешать" приложение до окончания выполнения операции. Соответственно выход из этой ситуации - запускать процессы получения данных в отдельных потоках.



Помимо того, что иногда будет требоваться передать данные в поток, так их еще нужно получить обратно в UI-поток и обработать, если есть, возникшие во время запроса ошибки. Задача не из простых. Но если использовать класс Task из .NET Framework 4, то задача немного упрощается, так как специально для этого класса я сделал несколько методов расширений, которые очень помогают в решении вышеописанных задач:

четверг, 17 января 2013 г.

WIX + NET 4.0 Framework + Microsoft Windows Installer 3.1

Очень часто, перед установкой программы, требуется проверить наличие нужных в системе компонентов. В данной статье я покажу как в WIX проверить наличие установленного NET Framework 4.0 и Microsoft Windows Installer 3.1.
Для начала создадим новый проект Windows Installer XML с говорящим названием - Setup. Добавим в наш проект файл Variables.wxi, в котором будут содержаться переменные, описывающие параметры нашего приложения:

Variables.wxi:
<?xml version="1.0" encoding="utf-8"?>
<Include>
  <?define ProductName="WPFCSHARP Program"?>
  <?define ProductVersion="1.0.0.0" ?>
  <?define ProductCode="A5C649E2-7180-401C-A188-B23A4E766432"?>
  <?define UpgradeCode="90BCED71-26CD-483E-AE93-0DB3510B7313"?>
  <?define Manufacturer="WPFCSHARP"?>
</Include>
Обратите внимание, что уникальные идентификаторы в вашем приложении должы быть другими. Для генерации GUID'ов в VIsual Studio используйте утилиту, которая находится в меню Сервис >> Создать GUID.

Затем изменим главный файл в проекте Product.wxs следующим образом:

Product.wxs :
  <?include Variables.wxi?>

  <Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="1049" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">

среда, 9 января 2013 г.

Как "звучит" Garbage Collector?

Читая книгу Джеффри Рихтера "CLR via C#. Программирование на платформе Microsoft .NET Framework 4.0 на языке C#", я наткнулся на интересный класс.

Code:
    internal sealed class GCBeep
    {
        ~GCBeep()
        {
            Console.Beep();
            if (!AppDomain.CurrentDomain.IsFinalizingForUnload() && !Environment.HasShutdownStarted)
                new GCBeep();
        }
    }

Этот код примечателен тем, что во время вызова деструктора класс воспроизводит звуковой сигнал, и если приложение еще не завершено, создает новый экземпляр себя же. Теперь если мы просто создадим экземпляр этого класса, то каждый раз, когда будет запускаться Garbage Collector, будет воспроизводится звуковой сигнал (так как этот класс каждый раз будет "подметаться" GC).