Was ganz nützlich für die Darstellung von Daten ist, ist das Accordion, welches ja auch bereits im AjaxControlToolkit vorkommt.
Nun die meisten werden das Ganze sicherlich rein nativ client-seitig mit JQuery und der Herumschlagerei von Div-Elementen verwendet haben.
Meine Überlegung war es, in Abhängigkeit zu einer Quelle (IEnumerable) die Accordion-Items generieren zu lassen.
Wie bin ich vorgegangen?
Als erstes habe ich mir das Markup eines Demo-Accordions auf der Webseite von JQuery angesehen.
Da es im .NET die Klasse HtmlGeneric gibt kann man mit dieser mit ein wenig Geschick viel anstellen
Also wir brauchen folgendes:
- Eine ASP.Seite mit einem Div-Element dass den Container für das Accordion darstellt
- Als nächstes brauchen wir eine Klasse, die uns den Accordion Markup generiert
- Und last but not least ein Model Element (Klassenelement aus unserem Modell
1. Erstellen der ASPX Seite
Der nachfolgende Markup-Code ist keine Magie und ziemlich schlank
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="AspNetWebFromJQueryUI.Index" %> <asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server"> <link type="text/css" href="Content/themes/base/jquery.ui.all.css" rel="Stylesheet" /> <script type="text/javascript" src="/Scripts/jquery-1.6.4.js"></script> <script type="text/javascript" src="/Scripts/jquery-ui-1.8.16.js"></script> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <script> $(function () { $("#Accordion").accordion(); }); </script> <div id="ResultDiv" runat="server"> </div> </asp:Content>
Einzig das Referenzieren von JQuery und JQueryUI sollte beachtet werden. Hierzu findet man auf JQueryUI die entsprechende Anleitung im Get started Teil.
2. Den Helper für das Accordion
Nun kommen wir zum Helper für die Erstellung des Markups für das Accordion, der wie folgt aufgebaut ist:
using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Web.UI; using System.Web.UI.HtmlControls; namespace AspNetWebFromJQueryUI.Controls { /// <summary> /// Responsible for creating an accordion base /// for using it with JQueryUI /// </summary> public static class AccordionHelper { /// <summary> /// Returns the complete HTML code for the accordion. /// </summary> /// <typeparam name="T">The model type.</typeparam> /// <param name="datasource">The items to show in the accordion</param> /// <see cref="http://jqueryui.com/demos/accordion/"/> /// <returns>The HTML Markup for an accordion in JQuery manner</returns> public static HtmlGenericControl CreateAccordion<T>(IEnumerable<T> datasource) { HtmlGenericControl accordion = new HtmlGenericControl {TagName = "div", ClientIDMode = ClientIDMode.Static, ID = "Accordion"}; accordion.InnerHtml = CreateContentDiv(datasource); return accordion; } /// <summary> /// Creates the content div's for putting the model /// content to it. /// </summary> /// <typeparam name="T">The model item (for example from the businessmodel)</typeparam> /// <param name="datasource">The items that are the datasource for the accordion</param> /// <returns>The HTML string for the accordion</returns> private static string CreateContentDiv<T>(IEnumerable<T> datasource) { StringBuilder sb = new StringBuilder(); if (datasource != null) for (int index = datasource.Count() - 1; index >= 0; index--) { if (index == 0) { sb.AppendLine(string.Format("<h3><a href=\"#\">{0}</a></h3>", CreateTitleElement(datasource.ToList()[index]))); sb.AppendLine(string.Format("<div>{0}</div>", CreateContentItemFromModel(datasource.ToList()[index]))); } else { sb.AppendLine(string.Format("<h3><a href=\"#\">{0}</a></h3>", CreateTitleElement(datasource.ToList()[index]))); sb.AppendLine(string.Format("<div>{0}</div>", CreateContentItemFromModel(datasource.ToList()[index]))); } } return sb.ToString(); } /// <summary> /// Foreach property in the model item it will be crated a desing /// like label: value of the property. /// </summary> /// <typeparam name="T">The model object</typeparam> /// <param name="model">The model item to treat</param> /// <returns>The content for the contentItems in the accordion</returns> private static string CreateContentItemFromModel<T>(T model) { StringBuilder sb = new StringBuilder(); model.GetType().GetProperties().ToList().ForEach(property => sb.AppendLine(string.Format(@"{0}: {1} <BR/>", property.Name, property.GetValue(model, null)))); return sb.ToString(); } /// <summary> /// Takes the first property of an object an set's it /// as title. /// </summary> /// <typeparam name="T">The model object</typeparam> /// <param name="model">The model item to treat</param> /// <returns>The content for the title in the accordion</returns> private static string CreateTitleElement<T>(T model) { StringBuilder sb = new StringBuilder(); PropertyInfo info = model.GetType().GetProperties().FirstOrDefault(); string title = string.Format(@"{0}: {1}", info.Name, info.GetValue(model, null)); return title; } } }
Was macht der Code?
- Er erstellt das Grundgerüst in welchem die Items reingepflanzt werden.
- Er erstellt einen Titel aus dem ersten Property des Modells und setzt diesen mit dem Wert des ersten gefundenen Properties von der Modellklasse
- Ist alles erledigt, gibt er den gesamten erstellen Markup zurück
3. Die Modellklasse
Meistens findet ja so ein Accordion bei einem Newsreader Verwendung. Eine solches News-Items hat die folgenden Eigenschaften:
- Titel
- Inhalt
- Veröffentlichungsdatum
Nachstehend die sehr einfache Modellklasse für ein News-Item.
using System; namespace AspNetWebFromJQueryUI.Model { public class NewsItem { public string Title { get; set; } public string Content { get; set; } public DateTime PublishDate { get; set; } } }
Wirklich ganz trivial…
4. Einbindung in unsere Seite
Die Einbindung in die Seite geschieht dann wie folgt:
- ResultatDiv der Seite mit einem runat=“server“ versehen
- Im Codebehind dem Control das generierte Accordion hinzufügen.
using System; using System.Collections.Generic; using System.Linq; using AspNetWebFromJQueryUI.Controls; using AspNetWebFromJQueryUI.Model; namespace AspNetWebFromJQueryUI { public partial class Index : System.Web.UI.Page { protected void Page_Init(object sender, EventArgs e) { //Create dummyData List<NewsItem> datasource = new List<NewsItem>(); for (int index = 0; index < 10; index++) { datasource.Add(new NewsItem() { Content = string.Format(@"Neuigkeitsinhalt {0}", index.ToString()), Title = string.Format(@"Neuigkeit {0}", index.ToString()), PublishDate = DateTime.Now.Subtract(new TimeSpan(index, index, index)) }); } this.ResultDiv.Controls.Add(AccordionHelper.CreateAccordion(datasource.OrderByDescending(n => n.PublishDate))); } } }
Somit wird beim Starten, alles in einem schönen von JQuery verwalteten Accordion gerendet.
ACHTUNG: Reflection funktioniert nicht in Abhängigkeit zu den .NET Sicherheitseinstellungen, daher muss zuerst überprüft werden, ob mit Reflection gearbeitet werden kann.
Für Anregungen und Fragen würde ich mich auf einen Kommentar freuen