Урок 2. Создаем своё приложение на Ext.NET, часть 1

в 9:23, , рубрики: .net, ASP.NET, ext, Ext.NET, Веб-разработка, метки: , ,
Контейнеры (Container, Panel, TabPanel, ViewPort) и разметки (BorderLayout, AccordionLayout, CardLayout)

Введение

Ну что же начнем. Нашей конечной целью будет создать интерфейс примерно похожий на Microsoft Outlook 2010. Почему именно этот интерфейс? Причина проста — потому что Ext.NET часто используется в корпоративном секторе или близком к нему и пользователь этой аудитории зачастую хочет видеть нечто похожее на Outlook. Плюс ко всему эта разметка довольно сложная и потому интересная. Не переживайте можно сделать и многие другие интерфейсы, но это все как-нибудь потом. Сразу оговорюсь, что мы не будем делать полную копию интерфейса Outlook, ограничимся только самым нужным.

Урок 2. Создаем своё приложение на Ext.NET, часть 1

Для начала создадим пустое ASP.NET приложение и назовем его "OutlookInterfaceWithExtNet".

Урок 2. Создаем своё приложение на Ext.NET, часть 1

Запустим «Package Manager Console (Tools -> Library Package Manager -> Package Manager Console)». И наберем следующую команду "PM -> Install-Package Ext.NET -Pre". С помощью NuGet импортируем Ext.NET и получим почти то же приложение, которое было в прошлом уроке

Урок 2. Создаем своё приложение на Ext.NET, часть 1

Подправим «Web.config», чтобы не добавлять везде ссылку на сборку с компонентами Ext.NET.

Урок 2. Создаем своё приложение на Ext.NET, часть 1

Удалим файл «Ext.NET.Default.aspx» из проекта, в этом проекте он нам не понадобится.

ViewPort, BorderLayout и AccordionLayout

Теперь когда все приготовления закончены, скопируем разметку из следующего примера http://examples.ext.net/#/ViewPort/Basic/Built_in_Markup/ в новый файл «Default.aspx».  Удалим регистрацию сборки, она у нас и так прописана в Web.config. Получим следующую разметку:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Viewport with BorderLayout - Ext.NET Examples</title>
</head>
<body>
    <ext:ResourceManager runat="server" />
    
    <ext:Viewport runat="server" Layout="BorderLayout">
        <Items>
            <ext:Panel 
                runat="server"
                Title="North" 
                Region="North"
                Split="true"
                Height="150"
                BodyPadding="6"
                Html="North"
                Collapsible="true"
                />
            <ext:Panel 
                runat="server" 
                Title="West" 
                Region="West"
                Layout="AccordionLayout"
                Width="225" 
                MinWidth="225" 
                MaxWidth="400" 
                Split="true" 
                Collapsible="true">
                <Items>
                    <ext:Panel 
                        runat="server" 
                        Title="Navigation" 
                        Border="false" 
                        BodyPadding="6"
                        Icon="FolderGo"
                        Html="West"
                        />
                    <ext:Panel 
                        runat="server" 
                        Title="Settings" 
                        Border="false" 
                        BodyPadding="6"
                        Icon="FolderWrench"
                        Html="Some settings in here"
                        />
                </Items>
            </ext:Panel>
            <ext:TabPanel runat="server" Region="Center">
                <Items>
                    <ext:Panel 
                        runat="server" 
                        Title="Center" 
                        Border="false" 
                        BodyPadding="6"
                        Html="<h1>Viewport with BorderLayout</h1>"
                        />
                    <ext:Panel 
                        runat="server" 
                        Title="Close Me" 
                        Closable="true" 
                        Border="false" 
                        BodyPadding="6"
                        Html="Closeable Tab"
                        />
                </Items>
            </ext:TabPanel>
            <ext:Panel 
                runat="server" 
                Title="East" 
                Region="East"
                Collapsible="true" 
                Split="true" 
                MinWidth="225"
                Width="225" 
                Layout="Fit">
                <Items>
                    <ext:TabPanel 
                        runat="server"
                        ActiveTabIndex="1" 
                        TabPosition="Bottom" 
                        Border="false">
                        <Items>
                            <ext:Panel 
                                runat="server" 
                                Title="Tab 1" 
                                Border="false" 
                                BodyPadding="6"
                                Html="East Tab 1"
                                />
                            <ext:Panel 
                                runat="server" 
                                Title="Tab 2" 
                                Closable="true" 
                                Border="false" 
                                BodyPadding="6"
                                Html="East Tab 2"
                                />
                        </Items>
                    </ext:TabPanel>
                </Items>
            </ext:Panel>
            <ext:Panel 
                runat="server"
                Title="South"
                Region="South"
                Split="true"
                Collapsible="true"
                Height="150"
                BodyPadding="6"
                Html="South"
                />
        </Items>
    </ext:Viewport>
 </body>
</html>

Мы видим на этой странице следующее дерево разметки, в скобках указаны важные нам атрибуты:

  • ViewPort
    • Panel (Region = «North»)
    • Panel (Layout=«AccordionLayout», Region=«West)
      • Panel
      • Panel

    • TabPanel (Region=»Center")
      • Panel (Title=«Center»)
      • Panel (Title=«Close me»)

    • Panel (Region=«East»)
      • TabPanel (TabPosition=«Bottom»)
        • Panel (Title=«Tab 1»)
        • Panel (Title=«Tab 2»)

    • Panel (Region=«South»)

Прежде чем начать разбирать, давайте посмотрим, что отобразится в браузере. Сделаем эту страницу страницей по умолчанию и запустим. Мы увидим область, размеченную на 5 частей, причем она занимает всю область страницы.

Урок 2. Создаем своё приложение на Ext.NET, часть 1

Теперь давайте поймем, как же все так получилось. Начнем с самого главного узла – с ViewPort. В Ext.NET есть довольно много разнообразных контейнеров. Основная роль, которых размещать в себе некоторое количество других контролов. Все они наследуются от класса AbstractContainer и имеют специальную коллекцию Items, которая и содержит дочерние контролы.
В нашей разметке в корне дерева мы видим специальный контейнер, называется он "ViewPort", он имеет одно интересное, выделяющее его от остальных контейнеров свойство, он занимает всю доступную область на странице. Вы можете, как угодно изменить размер окна браузера и всегда ViewPort будет растягиваться вместе с ним, занимая все доступное пространство. Поэтому его удобно использовать как базовый элемент в разметке. Но у него есть одно ограничение, на странице может быть только один ViewPort, что само себе является логичным, ведь и окно браузера у вас только одно.
Теперь давайте обратим внимание на атрибут Layout  у ViewPort, который имеет значение "border".  Он имеет его неспроста и обычно они используются вместе. Давайте уберем этот атрибут и посмотрим, что получится.

Урок 2. Создаем своё приложение на Ext.NET, часть 1

В принципе ничего страшного не случилось, только Элементы внутри нашего ViewPort встали друг над другом. Типичное поведение для блочных элементов в HTML. Причина кроется в том, что атрибут Layout (Разметка) указывает способ расположение элементов в контейнере. Есть еще LayoutConfig, который выполняет тонкую настройку разметки. Эти свойства определены в базовом классе «AbstractContainer» и все контейнеры в Ext.NET наследуют это свойство.

Урок 2. Создаем своё приложение на Ext.NET, часть 1

Если вам интересно, какие еще бывают Layout'ы, то можете посмотреть на http://examples.ext.net  в узле Layout. Сейчас мы будем обсуждать только те, что будут нам необходимы. Вы можете почитать неплохое руководство по разметке, правда, по ExtJS Pre, http://rawberg.com/wp-content/uploads/ExtJS-Layouts.pdf. В нем подробно изложены основные моменты работы с разметками, которые справедливы и для Ext.NET.

Урок 2. Создаем своё приложение на Ext.NET, часть 1

В нашем конкретном случае мы используем BorderLayout, он размещает дочерние элементы контейнера, в нашем случае это ViewPort, максимум на пять частей или минимум на одну. Чтобы понять по какому принципу он их размещает, давайте, обратим внимание на дочерние элементы ViewPort. Он содержит четыре Panel и один TabPanel и у каждого есть атрибут "Region", со значением из набора: "North ", «West», " Center ", " East ", " South". Как вы, наверное, уже догадались, они указывают на 4 стороны света и центральный элемент, т.е. на размещение этих элементов внутри контейнера ViewPort. Разметка "Border" имеет следующие правила:

  1. Всегда должен быть дочерний элемент с атрибутом Region=«Center».Поэтому должен быть как минимум один элемент в данной разметке
  2. Этот центральный элемент занимает место, которое осталось после выделения пространства всем остальным элементам, участвующим в разметке.

В принципе, ничего сложного в BorderLayout больше нет. Давайте подведем небольшой итог:

  1. В Ext.NET есть контейнеры, которые наследуются от AbstractContainer и содержат коллекцию дочерних элементов Items;
  2. Контейнеры, не влияют на расположение элементов, для этого используются свойства Layout и LayoutConfig;
  3. Есть специальный контейнер ViewPort, который занимает всю доступную область в окне браузера;
  4. Есть BorderLayout, который позволяет расположить в контейнере его дочерние элементы, с помощью атрибута Region.

Я так полагаю, что многие обратили внимание на панель со значением Region=«West» и заголовком «West», а вернее на значение ее атрибута Layout. Посмотрите на отображение ее дочерних элементов. Они сгруппированы в так называемую гармошку (accordion).  Это сделано с помощью значения знакомого нам уже атрибута — Layout=«accordion». В принципе, в этом нет ничего сложного, поэтому на AccordionLayout мы задерживаться не будем.

Container, Panel, TabPanel

Контрол Panel является основным контейнером в Ext.NET.

Урок 2. Создаем своё приложение на Ext.NET, часть 1

Рассмотрим основные свойства класса Panel:

Название свойства Тип Унаследовано от Описание
AnimCollapse bool AbstractPanel Указывает анимировать или нет сворачивание и разворачивание панели. Имеет смысл только, если свойство Collapsible равно true.
BottomBar Ext.Net.ToolbarCollection AbstractPanel Коллекция элементов, которые будут отображаться в самом низу панели
Closable bool AbstractPanel Можно ли закрыть панель
CollapseMode Ext.Net.CollapseMode AbstractPanel Определяет способ отображения кнопки сворачивания панели. Принимает одно из значений перечисления (Enum) CollapseMode:
Default, Mini, Placeholder. Имеет смысл только, если свойство Collapsible равно true. По умолчанию 'Default'.
Collapsible bool AbstractPanel Указывает, может ли панель сворачиваться. По умолчанию 'false'.
Defaults Ext.Net.ParameterCollection AbstractContainer Набор параметров, которые будут добавлены к каждому элементу контейнера 
DefaultType String AbstractContainer Указывает xtype для дочерних элементов по умолчанию. По умолчанию 'panel'. Xtype это уникальный идентификатор класса в ExtJS. Подробнее docs.sencha.com/ext-js/4-1/#!/api/Ext.AbstractComponent-cfg-xtype
FooterBar Ext.Net.ToolbarCollection AbstractPanel Коллекция элементов, которые будут отображаться в нижней части панели
Items Ext.Net.ItemsCollection<AbstractComponent> AbstractContainer Набор компонентов, которые будут отображаться внутри контейнера
Layout String AbstractContainer Указывает разметку элементов в контейнере
LayoutConfig Ext.Net.LayoutConfigCollection AbstractContainer Указывает параметры/настройки разметки элементов в контейнере
LeftBar Ext.Net.ToolbarCollection AbstractPanel Коллекция элементов, которые будут отображаться в левой части панели
RightBar Ext.Net.ToolbarCollection AbstractPanel Коллекция элементов, которые будут отображаться в правой части панели
Title String AbstractPanel Заголовок панели. По умолчанию ''
Tools Ext.Net.ToolsCollection AbstractPanel Набор кнопок, которые отображаются рядом с заголовком панели. Обычно используется для отображения кнопок помощь, свернуть, закрыть
TopBar Ext.Net.ToolbarCollection AbstractPanel Коллекция элементов, которые будут отображаться сверху панели

 
Для ускорения отрисовки на стороне клиента вместо Panel можно использовать Container — более простую реализацию AbstractContainer. Давайте посмотрим, что будет, если в качестве дочерних элементов ViewPort, мы будем использовать Container, а не Panel. Код мы будем использовать следующий:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Viewport with BorderLayout - Ext.NET Examples</title>
</head>
<body>
    <ext:ResourceManager ID="ResourceManager1" runat="server" />
    
    <ext:Viewport ID="Viewport1" runat="server" Layout="BorderLayout">
        <Items>
            <ext:Container ID="Panel1" 
                runat="server"
                Title="North" 
                Region="North"
                Split="true"
                Height="150"
                BodyPadding="6"
                Html="North"
                Collapsible="true"
                />
            <ext:Container ID="Panel2" 
                runat="server" 
                Title="West" 
                Region="West"
                Layout="AccordionLayout"
                Width="225" 
                MinWidth="225" 
                MaxWidth="400" 
                Split="true" 
                Collapsible="true">
                <Items>
                    <ext:Panel ID="Panel3" 
                        runat="server" 
                        Title="Navigation" 
                        Border="false" 
                        BodyPadding="6"
                        Icon="FolderGo"
                        Html="West"
                        />
                    <ext:Panel ID="Panel4" 
                        runat="server" 
                        Title="Settings" 
                        Border="false" 
                        BodyPadding="6"
                        Icon="FolderWrench"
                        Html="Some settings in here"
                        />
                </Items>
            </ext:Container>
            <ext:TabPanel ID="TabPanel1" runat="server" Region="Center">
                <Items>
                    <ext:Container ID="Panel5" 
                        runat="server" 
                        Title="Center" 
                        Border="false" 
                        BodyPadding="6"
                        Html="<h1>Viewport with BorderLayout</h1>"
                        />
                    <ext:Container ID="Panel6" 
                        runat="server" 
                        Title="Close Me" 
                        Closable="true" 
                        Border="false" 
                        BodyPadding="6"
                        Html="Closeable Tab"
                        />
                </Items>
            </ext:TabPanel>
            <ext:Container ID="Panel7" 
                runat="server" 
                Title="East" 
                Region="East"
                Collapsible="true" 
                Split="true" 
                MinWidth="225"
                Width="225" 
                Layout="Fit">
                <Items>
                    <ext:TabPanel ID="TabPanel2" 
                        runat="server"
                        ActiveTabIndex="1" 
                        TabPosition="Bottom" 
                        Border="false">
                        <Items>
                            <ext:Container ID="Panel8" 
                                runat="server" 
                                Title="Tab 1" 
                                Border="false" 
                                BodyPadding="6"
                                Html="East Tab 1"
                                />
                            <ext:Container ID="Panel9" 
                                runat="server" 
                                Title="Tab 2" 
                                Closable="true" 
                                Border="false" 
                                BodyPadding="6"
                                Html="East Tab 2"
                                />
                        </Items>
                    </ext:TabPanel>
                </Items>
            </ext:Container>
            <ext:Container ID="Panel10" 
                runat="server"
                Title="South"
                Region="South"
                Split="true"
                Collapsible="true"
                Height="150"
                BodyPadding="6"
                Html="South"
                />
        </Items>
    </ext:Viewport>
 </body>
</html>

Урок 2. Создаем своё приложение на Ext.NET, часть 1

Размеры сохранились и содержимое элементов осталось. Чисто визуально мы потеряли только заголовки панелей, границу и фон стал прозрачным.  Также потерялась небольшая кнопка, которая позволяла панели свернуться для увеличения места для центрального элемента, ее присутствие обеспечивалось значением следующего атрибута — Collapsible=«true». Но данный атрибут не поддерживается в Container и мы лишись этого функционала.
Давайте рассмотрим результаты профилировщика в обоих случаях – в случае использования Panel и в случае использования Container.

Урок 2. Создаем своё приложение на Ext.NET, часть 1
Результаты профилирования с использованием Container вместо Panel в ViewPort

Урок 2. Создаем своё приложение на Ext.NET, часть 1
Результаты профилирования с использованием Panel в ViewPort

Как видно из результатов, замена только 4 Panel на Container, уменьшило время на отрисовку более чем на 30мс (494 мс вместо 530мс) и количество вызовов функций JavaScript, на 7000(57236 вместо 64381). Что является довольно неплохим результатом, если учитывать, что обычно в Ext.NET приложениях используется несколько сотен Panel. Но если вы точно не уверены в выигрыше и преимуществах использования Container вместо Panel, я рекомендую использовать Panel. Зачастую это не приносит принципиального выигрыша в скорости, т.к. браузеры работают все быстрее, мощности клиентских машин тоже, а возможных проблем это может добавить в разы больше. Мы же не будем экономить и оставим Panel.
Следующий контейнер, который мы встречаем это "TabPanel" – панель для вкладок. Контрол является контейнером для Panel и каждый из них является вкладкой. Значение заголовка указывается в атрибуте "Title" контейнера, а если вы хотите, чтобы вкладку можно было закрыть, то обратите внимание на атрибут "Closable". TabPanel в своей реализации использует еще один интересный Layout — CardLayout. Подробно останавливаться на нем не будем. Вкратце, он представляет дочерние элементы контейнера как стопку карточек и отображает пользователю только верхнюю. Т.е. пользователю в каждый момент времени отображается только один элемент из его набора дочерних элементов. Чтобы понять, можете глянуть на следующий пример
Рассмотрим основные свойства класса TabPanel(т.к. TabPanel потомок AbstractPanel, то все свойства, описанные для Panel справедливы и для нее, но некоторые не будут работать т.к. не имеют смысла):

Название свойства Тип Унаследовано от Описание
ActiveTab
 
Ext.Net.AbstractComponent AbstractTabPanel Идентификатор, индекс или непосредственно вкладка, которая будет отображаться по умолчанию. Полезно, если вам нужно, чтобы при отображении TabPanel была открыта, допустим 2, вкладка
ActiveTabIndex int AbstractTabPanel Индекс вкладки по умолчанию
DeferredRender bool AbstractTabPanel При значении True элементы вкладки не будут загружены в браузер до тех пор, пока вкладка не станет активной или видимой. Это позволяет ускорить производительность при большом количестве элементов во вкладках.
При значении False элементы всех вкладок будут загружены сразу, зачастую понижает производительность. Используется в редких случаях: когда возникают проблемы с отображением контролов или когда пользователя раздражает задержка при нажатии на вкладку.
По умолчанию True
ItemCls String AbstractTabPanel CSS класс который будет добавлен к каждой вкладке.
По умолчанию «x-tabpanel-child»
MaxTabWidth int AbstractTabPanel Максимальная ширина вкладки
MinTabWidth int AbstractTabPanel Минимальная ширина вкладки
TabAlign Ext.Net.TabAlign AbstractTabPanel Направление вкладок. Либо справо налево(Ext.Net.TabAlign.Left), либо слева направо(Ext.Net.TabAlign.Left).
По умолчанию Ext.Net.TabAlign.Left
TabPosition Ext.Net.TabPosition AbstractTabPanel Положение заголовков вкладок. Либо сверху(Ext.Net.TabPosition.Top), либо (Ext.Net.TabPosition.Bottom).
По умолчанию Ext.Net.TabPosition.Top

Создаем основную базовую разметку

Теперь имея полученный багаж знаний, мы можем приступить к созданию самой базовой разметки нашего приложения. В нем не будет очень многого, но ведь мы только начинаем. Все панели нашего ViewPort'а остались на месте, но в соответствии с нашими требованиями они получили должное оформление. Давайте посмотрим на разметку, которая получилась в итоге, вы можете ее вставить в Default.aspx и поработать с ней самостоятельно.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>«a la Outlook» приложение, часть 1</title>
</head>
<body>
    <ext:ResourceManager ID="PageResourceManager" runat="server" />
    
    <ext:Viewport ID="AppMainViewport" runat="server" Layout="BorderLayout">
        <Items>
            <ext:Panel ID="MenuPanel" 
                runat="server"
                Title="Меню" 
                Region="North"
                Height="100"
                Html="Здесь будет меню"
                Collapsible="true">
                <Tools>
                    <ext:Tool Type="Help" runat="server"></ext:Tool>
                </Tools>
            </ext:Panel>
            <ext:Panel ID="LeftSideNavPanel" 
                runat="server" 
                Title="Папки"
                Region="West"
                Layout="AccordionLayout"
                Width="225" 
                MinWidth="225" 
                MaxWidth="400" 
                Split="true"
                Collapsible="true"
                CollapseMode="Placeholder">
                <Items>
                    <ext:Panel ID="MailLeftSideNavPanel" 
                        runat="server" 
                        Title="Почта" 
                        Border="false" 
                        BodyPadding="6"
                        Icon="Email"
                        Html="Здесь будет список папок почты"
                        />
                    <ext:Panel ID="CalendarLeftSideNavPanel" 
                        runat="server" 
                        Title="Календарь" 
                        Border="false" 
                        BodyPadding="6"
                        Icon="Calendar"
                        Html="Здесь будет календарь"
                        />
                    <ext:Panel ID="ContactsLeftSideNavPanel" 
                        runat="server" 
                        Title="Контакты" 
                        Border="false" 
                        BodyPadding="6"
                        Icon="FolderUser"
                        Html="Здесь будут контакты"
                        />
                    <ext:Panel ID="TasksLeftSideNavPanel" 
                        runat="server" 
                        Title="Задачи" 
                        Border="false" 
                        BodyPadding="6"
                        Icon="Tick"
                        Html="Здесь будут задачи"
                        />
                </Items>
            </ext:Panel>
            <ext:Panel ID="MainMailPanel" runat="server" Region="Center" Html="Здесь будет основная область для работы с почтой">
            </ext:Panel>
            <ext:Panel ID="TasksRightSidePanel" 
                runat="server" 
                Title="Встреч в будущем не намечено" 
                Region="East"
                Collapsible="true" 
                CollapseMode="Placeholder"
                Split="true" 
                MinWidth="225"
                Width="225"
                Html="Здесь будут отображаться текущие дела и встречи">
            </ext:Panel>
            <ext:Panel ID="AppMainStatusPanel" 
                runat="server"
                Region="South">
                <BottomBar>
                    <ext:StatusBar 
                        ID="AppMainStatusBar" 
                        runat="server"
                        DefaultText="Здесь будут отображаться статус приложения">
                    </ext:StatusBar>
                </BottomBar>
            </ext:Panel>
        </Items>
        
    </ext:Viewport>
 </body>
</html>

И если мы это запустим, то получим следующий вид нашей главной страницы:
Урок 2. Создаем своё приложение на Ext.NET, часть 1
В разметке нет ничего сложного, это все знакомые нам компоненты. Однако если у вас возникают вопросы, то пишите.
На этом мы остановимся. Основа нашего приложения заложена, хотя она обычно одинаковая для всех приложений. В следующей части мы сделаем еще один шаг — сделаем верхнее меню (Ribbon) и попутно разберемся с Toobar, Button, SplitButton и прочими другими интересными компонентами.
Проект можете скачать тут
Спасибо за внимание и приятного чтения!

Автор: Baidaly

* - обязательные к заполнению поля