Разширения за Grid View
Следващите раздели обсъждат няколко начина за разширяване на GridView. Ще научите как да показвате общи суми, как да създавате пълен отчет с главни детайли на една страница и как да показвате графични данни, извлечени от база данни. Ще видите също пример, който използва разширено управление на паралелността, за да предупреди потребителя за потенциални конфликти при актуализиране на запис.
Общо в GridView
Докато основната цел на Gr >ShowFooter е вярна. Това ще покаже сенчеста лента в долната част на GridView (която можете свободно да персонализирате по ваш вкус), но в нея няма да се показват данни. За да разрешите този проблем, ще трябва да добавите съдържание към GridView.FooterRow.
Да предположим например, че говорим за списък с продукти от тестовата база данни на Northwind. Един прост обобщаващ ред може да показва сумата или средната цена на артикулите. В следващия пример общият ред ще покаже общото количество на всички артикули на склад.
Първото нещо, което трябва да направите, е да решите кога да изчислите тази информация. Ако използвате ръчно обвързване, можете да извлечете обекта с данни и да го използвате за извършване на изчисления, преди да се обвържете с GridView. Въпреки това, ако използвате декларативно обвързване, е необходим различен подход. Има две опции за избор - извличане на данни от обекта с данни, преди мрежата да бъде обвързана, или извличане директно от самата мрежа, след като вече е била обвързана.
Следващият пример използва последния подход, тъй като предоставя свободата да използвате един и същ код за изчисление на общи суми, независимо от това кой източник на данни попълва контролата. това е същотови позволява да обобщите само редовете, показани на текущата страница, ако странирането е разрешено. Недостатъкът на решението е, че кодът е тясно свързан с GridView, т.к необходимата информация се извлича чрез нейната позиция с помощта на твърдо кодирани номера на колони.
В този пример продуктовата таблица с страници предоставя обобщена информация, посочваща общата цена на всички продукти, които в момента се показват на страницата:

За да попълни долния колонтитул, кодът в този пример отговаря на събитието GridView.DataBound. Това се случва веднага след като GridView се попълни с данни. В този момент вече нямате достъп до данни, но можете да навигирате в GridView като колекция от редове и клетки. Изчислената обща сума се вмъква в реда на долния колонтитул.
По-долу е пълният код:
Полученият ред има същия брой колони като останалата част от мрежата. В резултат на това, ако искате текстът да обхваща няколко клетки (както в този пример), трябва да конфигурирате това, като използвате свойството ColumnSpan на съответната клетка. В този пример първата клетка обхваща три колони (собствената колона и две съседни отдясно).
Изглед родител-дете в една таблица

Основният трик е да създадете GridView за родителската таблица, съдържащ вграден GridView за всеки ред. Тези дъщерни GridView контроли се поставят в родителския GridView с помощта на TemplateField. Единственото усложнение е, че не можете да обвържете дъщерните контроли на GridView в същото време, когато обвържете родителския, тъй като родителските редове все още не са създадени. Вместо това е необходимоизчакайте събитието GridView.DataBound да се задейства върху родителския елемент.
Получаване на изображения от базата данни
Примерите досега са извличали текст, числа и дати. Базите данни обаче често съхраняват двоични данни, като например графични изображения. Например може да има таблица с продукти, която съдържа изображения на всеки елемент в двоично поле. Извличането на тези данни в ASP.NET страница е доста лесно, но не е толкова лесно да се покажат.
Основният проблем е, че за да покажете изображение на HTML страница, трябва да добавите дескриптор на графично изображение, който препраща към отделен файл в своя src атрибут, както е показано по-долу:
За съжаление, това не е много полезно, ако трябва динамично да показвате графични данни. Въпреки че е възможно да зададете атрибута src в кода, няма начин програмно да зададете съдържанието на изображение. Възможно е първо да запишете данните във файл с изображение на твърдия диск на уеб сървъра, но този подход може да бъде изключително бавен и да губи място на диска. В допълнение, той също генерира грешки, свързани с паралелността, когато много заявки се обслужват едновременно и всички те се опитват да пишат в един и същ файл.
В тези ситуации решението е да се използва отделен ASP.NET ресурс, който връща директно двоични данни. След това тези двоични данни могат да се използват в контроли на други уеб страници. За да разрешите този проблем, вие също трябва да изоставите обвързването на данни и да напишете персонализиран ASP.NET код. Необходимото решение е разработено стъпка по стъпка в следващите раздели.
Като препоръка, не забравяйте, че съхраняването на графични изображения в база данни работи добрекогато не надвишават разумен размер (например 5 MB) и не изискват често редактиране в приложенията.
Дисплей на двоични данни
ASP.NET не се ограничава до връщане на HTML съдържание. Всъщност с Отговора. BinaryWrite() може да върне необработени байтове, напълно заобикаляйки модела на уеб страницата.
Следващата страница използва тази техника с таблицата pub_info в базата данни pubs (друга стандартна база данни, която се доставя с SQL Server. Можете да я инсталирате с помощта на Northwind и pubs Sample Databases за SQL Server 2000). Тази страница извлича полето за лого, съдържащо данни за двоично изображение. След това тези данни се извеждат директно към страницата, както е показано по-долу:
Когато използвате BinaryWrite(), вие се отклонявате от модела на уеб страницата. Ако добавите други контроли към страницата, те няма да се показват там. По същия начин Response.Write() няма да има ефект, тъй като вече не създавате HTML страница. Вместо това вие връщате двоични данни. Следващите раздели ще покажат как да разрешите този проблем и да оптимизирате подхода.
Ефективно четене на двоични данни
Двоичните данни могат лесно да нараснат до огромни размери. Въпреки това, ако имате работа с голям графичен файл, тогава горният пример ще демонстрира очевидно лоша производителност. Проблемът е, че използва DataReader, който зарежда един по един запис в паметта. Това е по-добро от DataSet (което зарежда целия набор от резултати наведнъж), но все пак не е идеално, ако размерът на полето е достатъчно голям.
Ето как да преработите предишната страница, за да използвате последователен достъп:
Методът GetBytes() връща стойност, указващаколичеството получени данни. Ако трябва да определите общия брой байтове в поле, просто предайте нулева препратка вместо буфер, когато извиквате метода GetBytes().
Интегриране на изображения с друго съдържание
Методът Response.BinaryWrite() създава проблем, когато става въпрос за интегриране на графични данни с други контроли и HTML маркиране. Това е така, защото ако използвате BinaryWrite(), за да върнете данни за изображения от ниско ниво, вие губите възможността да добавяте допълнително HTML съдържание.
За да се справите с този проблем, трябва да създадете друга страница, която ще извика кода, който генерира изображението. Най-добрият начин да направите това е да замените страницата за генериране на изображения със специален HTTP манипулатор, който ще генерира графичен изход. В резултат на това можете да спестите от разходите за пълния модел на ASP.NET Web Forms. който все още не може да се използва.
Създаването на правилния HTTP манипулатор е доста просто. Трябва да внедрите интерфейса IHttpHandler и метода ProcessRequest(). HTTP манипулаторът ще извлече идентификатора на записа, който ще бъде показан от низа на заявката.
По-долу е пълният код на манипулатора на HTTP:
Генерираният HTTP манипулатор трябва да се добави към файла с тип Generic Handler:

Вече можете да получите графични данни, като направите заявка към URL адреса на HTTP манипулатора за идентификатора на реда, който искате да извлечете. Ето един пример:
По-долу е примерна реализация на страница с много контроли и изображения на лого. Той използва следния ItemTemplate в GridView:

Този подход на манипулатор на HTTP работи добре, когато искате да създадете подробна страница с информация за единичен запис. Например, можете да изведетесписък с издатели и след това показване на графика, представяща издателя, когато потребителят направи избор. Това решение обаче не е толкова ефективно, ако искате да покажете всички графики за всички издатели наведнъж, като например в контрола на списък. Подходът работи, но не е достатъчно ефективен, т.к всяко изображение се извлича с помощта на отделна заявка за манипулатор на HTTP (и следователно допълнителна връзка с база данни).
Решението на този проблем е да се създаде HTTP манипулатор, който първо проверява дали изображението е в кеша, преди да го извлече от базата данни. След това, преди да обвържете GridView, ще трябва да изпълните заявка, която ще върне всички записи с техните графични данни и ще ги зареди в кеша.