воскресенье, 6 июня 2010 г.

Пример разработки собственного отчета на Silverlight

В этой статье я бы хотел показать, как можно быстро создать гибкий и красивый (зависит от фантазии дизайнера) отчет с применением технологии Silverlight. К числу преимуществ WEB-отчета (Silverlight в частности) можно вписать:
  • Простота развертки (не надо каждый раз при обновлении разворачивать на клиентах msi'ники)
  • Возможность просмотра как в навигаторе (настроив папку на отображения отчета по URL), так и вне его (просто в браузере).
  • Так как физически отчет находится на сервере – это значит, что удобно использовать MSSQL Server напрямую для выборки данных для отчета (хотя никто не мешает задействовать и DV API)

Silverlight предоставляет возможность создавать действительно «богатые» интерфейсы (rich UI) декларативно на языке XAML (так же, как и в WPF). Например, небольшими усилиями можно сделать таблицу, похожую на ту, что используется в навигаторе: 

При том, что исходный код страницы на C# выглядит очень минималистично:


using System.Windows.Data;

namespace IDoc.DvWebReports
{
public partial class MainPage
{
public MainPage()
{
InitializeComponent();
//генерация набора тестовых данных:
Tasks = new PagedCollectionView(TaskInfo.GetTaskInfoForTest());
//группировка:
Tasks.GroupDescriptions.Add(new PropertyGroupDescription("Author"));
Tasks.GroupDescriptions.Add(new PropertyGroupDescription("Executer"));
}

///
/// Поручения
///

public PagedCollectionView Tasks { get; set; }
}
}

А представление этих тестовых данных (через Binding) полностью настраивается декларативно в XAML по средствам дизайнера в Visual Studio или такого интересного инструмента, как Expression Blend. На создание такого «фейкового» отчета у меня ушло меньше часа. 

Теперь перейдем к «реальным отчетам». В качестве примера, рассмотрим отчет о кол-ве созданных в системе карточек (в виде круговой диаграммы). Silverlight – это, по сути, клиентская часть, поэтому в проекте SL приложения мы не можем получить прямой доступ к данным (например, по средствам ADO.NET). Поэтому нам необходима отдельная служба, которую очень просто реализовать, используя технологию WCF. Ну и наконец, нам нужен ASP.NET проект, который будет хостом для нашего клиентского xap пакета (Silverlight приложения) и нашей службы WCF (с basicHttpBinding, т.к. только этот вид привязки поддерживается сильверлайтом). Структура солюшна в VS выглядит следующим образом:

Для развертки всего решения достаточно воспользоваться командой Publish и опубликовать на удаленном сервере прямо с машины разработчика.
В качестве доступа к данным в своём примере я использовал “недо-ОRM” LINQ to SQL, в котором накидал в дизайнере пару нужных для отчета таблиц и составил вот такой запрос:

    /// 
/// Получить информацию по кол-вам карточек в системе
///

public static CardsCountInfoRow[] GetCardCountsInfo(string connectionString,
DateTime rangeStart, DateTime rangeEnd)
{
using (var dataContext = CreateDataContext(connectionString))
{
var result =
from instancesGroup in
(from instance in dataContext.dvsys_instances
join instanceDate in dataContext.dvsys_instances_dates
on instance.InstanceID equals instanceDate.InstanceID
where
//Не удалена
(!instance.Deleted.HasValue || !instance.Deleted.Value) &&
//Не шаблон
(!instance.Template.HasValue || !instance.Template.Value) &&
//создана в указанный период
instanceDate.CreationDateTime >= rangeStart &&
instanceDate.CreationDateTime <= rangeEnd
group instance by instance.CardTypeID into g
select new { CardTypeID = g.Key, Count = g.Count()})
join def in dataContext.dvsys_carddefs
on instancesGroup.CardTypeID equals def.CardTypeID
select new CardsCountInfoRow(instancesGroup.Count, def.Icon,
def.CardTypeID, def.XMLSchema);
return result.ToArray();
}
}

Исходный код страницы отчета:

using System;
using System.Windows;
using DvReports.Reporting;

namespace DvReports
{
public partial class MainPage
{
public MainPage()
{
InitializeComponent();
RangeStart = new DateTime(DateTime.Now.Year, 1, 1);
RangeEnd = DateTime.Now;
}

///
/// Начало периода создания карточек
///

public DateTime RangeStart { get; set; }

///
/// Окончание периода создания карточек
///

public DateTime RangeEnd { get; set; }

private void btShowData_Click(object sender, RoutedEventArgs e)
{
var client = new ReportServiceClient();
client.GetCardCountsInfoCompleted += GetCardCountsInfoCompleted;
//посылаем запрос службе
client.GetCardCountsInfoAsync(RangeStart,
RangeEnd == DateTime.MinValue ? DateTime.MaxValue : RangeEnd);
}

//пришел ответ
private void GetCardCountsInfoCompleted(object sender, GetCardCountsInfoCompletedEventArgs e)
{
pieChart.Visibility = Visibility.Visible;
//отдаем данные диаграмме
pieChart.DataContext = e.Result;
}
}
}

Далее на XAML описал представление, развернул сайт на IIS и указал в одной из папок дв его отображение по URL:


На этом не остановился, и там же сделал ещё один отчет – отчет по продолжительностям сессий у сотрудников:


Тут используется обычный компонент ListBox с применением такой интересной "фичи", как DataTemplate – шаблон представления данных элемента, который удобно создавать в Expression Blend:

Для исполнения Silverlight приложений на клиентах, у них должен быть установлен Silverlight Runtime (~9mb), при этом наличие исполняемой среды .NET какой-либо версии не обязательно. Cовместимость Silverlight с различными операционными системами можно увидеть в таблице тут

Некоторые ссылки по теме:


  1. Step by step руководство по созданию Silverlight + WCF приложения 
  2. Видео-доклады на techdays.ru по Silverlight и WCF 

Исходники демонстрационных приложений: DvReportsSample и DataGridSample

3 комментария:

  1. А возможно определить текущего пользователя, чтобы отчет был сформирован с учетом его прав?

    ОтветитьУдалить
  2. Теоретически да, но я вижу только давольно сложный способ с созданием собственной карточки-хоста (с WebBrowser) которая бы запускала отчет с нужными параметрами.

    ОтветитьУдалить
  3. могли бы вы перезалить Исходники демонстрационных приложений, либо отправить их на почту a1exander.so8ol@gmail.com
    ________________________________
    С уважением Александр

    ОтветитьУдалить