Alternatywne podejście do “TabControl”

Myślę, że każdy, kto korzysta z rozmaitych stron/aplikacji choć raz spotkał się zakładkami (ang. tabs). Z tego względu nie opiszę co to jest, kto nie wie może zajrzeć tutaj, ale pokażę alternatywne podejście jak można coś takiego (TabControl) zrealizować i zastosować na stronie internetowej. Przykład, który zaprezentuję wykorzystuje ASP.NET 4 WebForms w związku z tym, że sam pomysł zrodził się podczas tworzenia projektu opartego właśnie na tej technologii. Teoretycznie sama koncepcja abstrahuje od technologii więc zachęcam do lektury również tych, którzy nie są zwolennikami WebFormsów.

Zanim przejdę do realizacji i przykładu opiszę pokrótce specyfikę zadania. Odłożę na razie na bok detale i załóżmy, że chcemy wdrożyć do projektu coś takiego:

Tabs

W zasadzie na tą chwilę problemu nie ma. Każdy zaprawiony w boju developer zaciągnie jQuery UI, AjaxControlToolkit, Juice UI lub jeszcze inne cudo i voilà, gotowe! Taka reakcja jest jak najbardziej słuszna i pożądana do momentu, kiedy nie znamy docelowej zawartości zakładek. Jeżeli przeznaczeniem zakładek jest wyświetlanie statycznych danych bez dodatkowych kontrolek, logiki i innych bajerów to mamy szczęście, ponieważ to jest podstawowy, a zarazem najprostszy przypadek. W takiej sytuacji możemy z powodzeniem wykorzystać którąś z wymienionych wcześniej bibliotek i problem jest rozwiązany.

Gdyby w życiu zawsze było tak pięknie i kolorowo to nie miałbym po co pisać dalej i zakończyłbym wpis na poprzednim paragrafie. Na (nie)szczęście zazwyczaj zmagamy się z zadaniami, które nijak mają się do przykładów zamieszczonych w dokumentacji, czy książce. Tak jest też w przypadku, gdy założymy, że zawartość tabów to np. gridy z dynamicznie ładowanymi danymi, wykresy, czy cokolwiek innego wykraczającego poza standardowy przypadek. Oczywiście w takiej sytuacji również możemy wykorzystać którąś z podanych bibliotek, podmienić zawartość i zapomnieć o temacie. Jeżeli tak to w czym problem?

Problem wynika z podejścia jakie stosują wymienione przeze mnie biblioteki. Najpierw wszystkie zakładki są renderowane, a co za tym idzie dane zostają pobrane, wykonana jest jakaś wewnętrzna logika – to wszystko po to, aby na końcu ustawić jedną aktywną zakładkę i ukryć zawartość pozostałych. Wada takiego rozwiązania powinna nasunąć się sama. Co jeżeli nie zawsze użytkownik będzie przechodził przez wszystkie zakładki? Po co mamy ładować zbędne (w danym kontekście) dane? Co jeżeli potrzebujemy specyficznego zachowania, które może (choć nie powinno) wpłynąć na kontrolki w innych zakładkach? Odpowiedzią na powyższe (i nie tylko) pytania jest rozwiązanie, które chcę zaproponować.

Zamiast zaprzęgać do pracy zewnętrzne biblioteki wykorzystam proste połączenie kontrolek dostępnych wraz z .NET. czyli MenuList + Nested Master Page + ContentPlaceholder. Do tego połączenia dorzucę sitemapę i trochę css’a. Ok, do roboty. Wykonanie całości zamknie się w kilku krokach.

Po stworzeniu standardowego projektu ASP.NET WebForms tworzymy plik Nested Master Page wybierając jako plik nadrzędny Site.master. Stworzony plik będzie stanowił ramę dla naszej kontrolki. Następnym krokiem jest wstawienie do naszej “ramy” kontrolek: MenuList opartej na sitemapie oraz ContentPlaceholder. ContentPlaceholder będzie kontenerem, do którego zostanie załadowana zawartość zakładki w zależności od kontekstu (adresu URL). W efekcie po wykonaniu tych kroków otrzymamy coś takiego:

Zawartość pliku TabHeaders.sitemap

Zawartość pliku TabContainer.master

Fragment pliku Web.config (znajdujący się wewnątrz znaczników <system.web></system.web>)

Kolejny krok to stworzenie konkretnych zakładek, które w tym przypadku są plikami *.aspx dziedziczącymi po pliku TabContainer.master (w okienku Add New Item wybieramy opcję Web Form using Master Page). Poszczególne zakładki będą ładowane dynamicznie, a na tą chwilę całość wygląda tak:

Tabs without CSS

Zawartość pliku Tabs\Tab1.aspx

Zawartość pliku Tabs\Tab2.aspx

Jak widać nie jest to jeszcze oczekiwany efekt, ale dodając odrobinę stylu CSS otrzymamy dokładnie to, do czego dążyliśmy:

Tabs

Fragment pliku Site.css

Największą korzyścią takiego rozwiązania jest to, że minimalnym nakładem pracy, nie napisaliśmy ani jednej linijki w code behind!, zakładki są ładowane na żądanie. Dzięki temu nie jest wykonywana dodatkowa praca po stronie serwera. Wykorzystując mechanizmy dostępne w ASP.NET nie musimy podpinać żadnych zewnętrznych komponentów, co również można uważać za plus.

Jedyną niedoskonałością przedstawionego rozwiązania, jaką udało mi się stwierdzić, jest fakt, że przełączanie pomiędzy zakładkami powoduje przeładowanie całej strony, co nie zawsze może być porządane. W celu wyeliminowania tej niedoskonałości można pomyśleć o zaprzęgnięciu AJAXa, aczkolwiek ten temat zostawiam chętnym jako zadanie domowe :).

3 comments on “Alternatywne podejście do “TabControl”
  1. Pingback: dotnetomaniak.pl

    • Kolejna ciekawa alternatywa, dzięki :). U mnie w projekcie było zastrzeżenie żeby JavaScript w miarę możliwości był ostatecznością, dlatego wyprowadziłem takie rozwiązanie.

Say something

Your email address will not be published. Required fields are marked with a grey bar.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">