Asp.net: ListView з різних сторін (исходники), Різне, Програмування, статті

Елемент управління ListView був представлений в. Net Framework 3.5 як заміна застарілого GridView. Новий елемент має більш розширений функціонал, ніж його попередник, але в теж час позбавлений деяких внутрішніх механізмів, що втім цілком наслідок з розширеною універсальності ListView. Серед відмінностей ListView і GridView можна назвати і гнучку настройку розмітки, що дозволяє виводити дані не тільки в табличному вигляді, але і взагалі в будь-якому якому забажає програміст. Завдяки шаблонам ItemTemplate, EditItemTemplate, InsertItemTeplate можна налаштувати зовнішній вигляд при будь-якому з станів ListView: редагуванні або виборі елемента.

Я вирішив написати цю статтю, щоб поділитися досвідом роботи з ListView, привести деякі способи вирішення спільних завдань, а також описати проблеми з якими я зіткнувся і які в мене вийшло вирішити не дуже красиво. Можливо, що при обговоренні статті знайдуться більш гнучкі рішення описаних задач, чому я буду тільки радий.

Зміст




Сортування


На відміну від GridView, в ListView немає вбудованої в редактор підтримки реалізації механізму сортування стовпців. На мій погляд, відсутність такої підтримки обумовлено тим, що ListView на відміну від GridView став здатний рендерить дані не тільки в табличному вигляді. Втім, навіть за відсутності механізму, додавання сортування в таблицю ListView – це, напевно, найлегше з того, що описано в цій статті. Розглянемо реалізацію на конкретному прикладі:





  <th class=”bankTd”>
<asp:LinkButton ID=”sortBank” runat=”server” CommandName=”sort” CommandArgument=”Bank.shortName” Text = “Банк” />
</th>

Тут CommandArgument=”Bank.shortName” вказує на те, який стовпець з джерела даних сортувати.


Відмова від AlternatingItemTemplate


AlternatingItemTemplate призначений для опису шаблону парних елементів списку. Це дозволяє рендерить таблиці і інші типи наборів даних в красивому вигляді, наприклад зробити так, що фони рядків даних у таблиці будуть чергуватися. В цілому, окремий шаблон – це звичайно, добре, але найчастіше вся різниця між рядками в таблиці полягає тільки в різному фоні або різних класах css. В цьому випадку об’ємний шаблон мені здається надлишковим і я пропоную інше рішення (підглянуте в інтернеті):





  ItemTemplate>
<tr Container.DataItemIndex % 2 == 0 ? “” : ” class=”alt”” %>>

У даному прикладі, замість того, щоб вводити в код AlternatingItemTemplate, я підставляю для парних рядків особливий css-клас. До речі, в реальному проекті це дозволяє заощадити мені близько 30 рядків коду.

Вибір елемента


ListView як і GridView пропонує механізм вибору рядка з набору даних. Вибір даних затребуваний у багатьох задачах з обробки інформації та ListView пропонує крім підтримки такого вибору ще й сильний механізм шаблонів. Що це означає? Це означає, що вибрані дані можна представити зовсім не так як вони були представлені в загальному наборі даних. Наприклад, можна розширити звичайний рядок записи і вивести додаткові дані, вивести додаткову панель інструментів по роботі з даними, додати додаткові посилання розширюють уявлення про вибраних даних. Продемонструю приклад:

Є така табличка:

А ось як виглядає результат вибору даних в ній:

При використанні ajax робота з такою табличкою для кінцевого користувача стає зручним і приємним. Живий приклад можна спробувати тут. Неважко помітити, що після вибору даних користувач отримує доступ до розширеної інформації і до додаткових сервісів, в даном випадку до друку даних, але тут може бути і редагування, приховування, видалення даних, у разі коли з даними працює їх творець або особа має право на ці операції.
Я не буду приводити в даному прикладі рядків коду, тому що реалізація не виходить за рамки звичайного, все реалізується в SelectedItemTemplate, в котрому замість одного рядка tr в даними випадку телефон три: стара жирним шрифтом, розширена інформація та панель інструментів.

Об’єднання осередків у колонці


Розглянемо приклад:

Вельми поширена ситуація, коли необхідно об’єднати повторювані по вертикалі дані в одну клітинку. В GridView таке завдання мною вирішувалася через подію OnRowDataBound, в якому можна було отримати доступ до поточної оброблюваної рядку і присвоїти потрібної осередку потрібний rowspan, а так же приховати непотрібні осередки. В ListView, на жаль, схожого інструменту немає. Більш того на даний момент мені не відомий аналогічний спосіб вирішення задачі. Пропонований мною спосіб строго кажучи не реалізує об’єднання осередків в ListView, а тільки маскує дані. Маємо таку розмітку:





    <ItemTemplate>
<tr runat=”server”>
<td class=”bankTd” runat=”server” id=”bankName” style=””>
<asp:HyperLink ID=”hlBank” runat=”server” Text=”” NavigateUrl=”test.aspx”>asp:HyperLink>
</td>


Тут представлений шматочок tr в якому є td, який і є метою об’єднання в разі повторюваних даних. Пропоную вихідний текст методу GetRowspanVisible:





  private string _bankName = “”;
public string GetRowspanVisible(string bankName)
{
string result = “border: 0px; border-left: solid 1px #C0C0C0; font-size: 0px;”;
if (Request.Browser.Browser == “IE”)
result = “visibility: hidden; border: 0px; border-left: solid 1px #C0C0C0;”;
if (_bankName != bankName)
{
_bankName = bankName;
result = “border-top: solid 1px #C0C0C0; border-left: 1px; border-bottom: 0px;”;
}
return result;
}

Код не претендує на витонченість. Я приймаю будь-які конструктивні пропозиції щодо його переробці. Відразу скажу, що зав’язка на стилі була обрана через те, що через класи такий підхід особисто у мене не запрацював. Отже: як можна бачити, при обробці осередків в стовпці їм присвоюється різний стиль, в залежності від того, що потрібно: приховати або показати. Таким чином, користувач побачить дані тільки в першій осередку, і порожні поля в наступних. Результат можна подивитися на малюнку вище. Мінусом такого рішення, крім усього іншого, є, зрозуміло, прив’язка відображуваних даних до верхньої межі, так як ці дані є елементом верхнього рядка і не містять rowspan.

Хотів би зауважити, що рішення далеко від ідеалу, навіть я сам це розумію. Але тривалі пошуки і консультації з камрадами ні до чого не привели, іншого рішення поки на руках немає. Буду радий побачити альтернативи і з задоволенням позбудуся від поточної реалізації. Поки ж, що є, то є. Чекаю ваших коментарів.

Використання DropDownList для lookup при редагуванні


В принципі завдання просте, але я все одно вирішив привести рішення в даній статті. В listview при редагуванні потрібно виводити DropDownList який би заповнювався даними з стороннього джерела довідкових даних і бінді до нашого джерела даних для listview. Приклад:

Рішення, як я вже сказав, просте:





asp:DropDownList ID=”ddlMetals” runat=”server” DataSourceID=”dsMetalDic” DataTextField=”name” DataValueField=”id” SelectedValue=””>asp:DropDownList>

Тут dsMetalDic – довідкові дані, Bind (“metalId”) – Біндінг до нашого джерела даних для ListView.

Запит на видалення


При видаленні даних важливо запитати у користувача підтвердження на виконання операції. При роботі з ListView можна використовувати наступне рішення. Визначимо функцію javascript:





  “text/javascript”>
function OnDeleteClick()
{ return confirm (“Видалити дані?”);
}

Використовуємо її в елементі який відповідає за видалення даних:





asp: LinkButton ID = “DeleteButton” runat = “server” CommandName = “Delete” Text = “Видалити” OnClientClick = “return OnDeleteClick ();” />

Редагування та збереження кількох рядків відразу


Часом необхідно вивести відразу весь набір даних складається з багатьох рядків в режимі редагування.

Вирішується це завдання через ItemTemplate і, загалом-то, це тривіальна задача. Інша справа як зберегти зміни у всіх цих рядках одним натисненням кнопки “Зберегти все”? Рішення нижче:





    foreach (var item in lvEdit.Items)
{
lvEdit.UpdateItem(item.DataItemIndex, true);
}

Де lvEdit – це ListView.

Приховування DataPager


Коли сторінка в таблиці одна, то відображати Pager не має сенсу, тому будемо приховувати. Складність полягає в тому, що в стандартному варіанті реалізації посторінкового розбивки даних доступу до елемента DataPager немає. Але ми знайдемо його і приховаємо наступним нехитрим способом:





  protected void rlv_DataBound(object sender, EventArgs e)
{
ListView listView = sender as ListView;
if (listView != null)
{
DataPager pager = listView.FindControl(“dp”) as DataPager;
if (pager != null)
pager.Visible = pager.PageSize < pager.TotalRowCount;
}
}

Тут rlv_DataBound – це оброблювач події OnDataBound у ListView, dp – ім’я нашого DataPager, який “вбудований” через шаблони в ListView.

Динамічна зміна запитів для ListView


Змінити запит для ListView не так вже й тривіально як може здатися коли ми використовуємо LinqDataSource. Я знаю одне рішення, яке наведу нижче:





  protected void dsResume_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
e.Result = Query;
}

Тут dsResume_Selecting – це оброблювач події OnSelecting у LinqDataSource.

Висновок


У цій статті я постарався висвітлити багато аспектів роботи з ListView, привів декілька прикладів і запропонував кілька рішень стандартних і не дуже завдань. Втім, я розумію, що багато завдань можуть бути вирішені іншим способом, можливо навіть більш цікавим. Чекаю конструктивних пропозицій, альтернативних рішень, коментарів і вказівок на помилки, які ви знайдете. Стаття писалася тривалий час, прошу вибачення за можливі помилки при наборі тексту.


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*