(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Всплывающее меню для одностраничного портала (исходники)

Источник: hardline
Золотухин Роман

Недавно решил изучить ASP.NET и одновременно создать что-нибудь полезное, посложнее "Hello, world!". Первое знакомство с ASP.NET у меня началось с IBuySpy. Довольно быстро разобравшись с этим Shared Source проектом, я начал его перекраивать под свои нужды. В итоге осталось довольно мало оригинального кода, кроме части ядра (ибо, зачем изобретать велосипед? :)). Кроме всего прочего,  хотелось сделать больше функциональности,  например, всплывающее меню. В сети много примеров всяких всплывающих менюшек,  в том числе и исходников Open Source. Но они, как правило, сложны и не очень подходили под мои нужды. Поэтому я решил написать простое меню в виде пользовательского элемента и предложить Вам результаты своего творчества. В результате должно получиться это:


 

1. Реализация базы данных

Начнем с написания базы данных. Для этой статьи я немного переделал таблицу Tabs из IBuySpy:

  CREATE TABLE [Tabs] 
  (
              [TabID] [int] IDENTITY (1, 1) NOT NULL,
              [TabOrder] [int] NOT NULL,
              [TabName] [nvarchar] (50) NOT NULL,
              [ParentTab] [int] NOT NULL 
  ) ON [PRIMARY]
  GO
  

TabID - идентификатор закладки,

TabOrder - порядковый номер закладки,

TabName - имя закладки,

ParentTab - указывает на идентификатор родительской закладки или имеет -1, если это верхний уровень меню.

Также необходимо написать пару процедур. Одну для составления списка меню из закладок (Tabs):

  CREATE PROCEDURE GetMenuItems 
  AS 
  SELECT   
      TabID, 
      TabOrder, 
      TabName 
  FROM 
      Tabs 
  WHERE 
      ParentTab = -1 
  ORDER BY 
      TabOrder 
  GO 
  

И еще одну для получения подменю для текущей закладки:

  CREATE PROCEDURE GetSubMenuItems 
  ( 
      @ParentTab int 
  ) 
  AS 
  SELECT   
      TabID, 
      TabOrder, 
      TabName 
  FROM 
      Tabs 
  WHERE 
      ParentTab = @ParentTab 
  ORDER BY 
      TabOrder 
  GO 
  

Надеюсь, тут все ясно. В принципе, можно обойтись только второй процедурой, передавая ей в качестве параметра -1 для заглавного меню. Но для большей простоты и наглядности оставим все как есть.

В качестве примера наполним таблицу следующими значениями:

На этом наша работа с SQL Server закончена, переходим к кодированию проекта.

2. Кодирование пользовательского элемента

Создадим для сего произведения новый проект. Он будет состоять из простой формы с таблицей для тестирования, класса для доступа к данным и собственно пользовательского элемента.

Для доступа к данным из базы создадим свой класс DataSource. Вот его код:

  using System; 
  using System.Configuration; 
  using System.Data; 
  using System.Data.SqlClient; 
  namespace Daenur.TabList 
  { 
    /// <summary> 
    /// Summary description for DataSource. 
    /// </summary> 
    public class DataSource 
    { 
      public SqlDataReader GetMenuItems() 
      { 
        // создаем соединение (connectionString берем из Web.config) 
        SqlConnection myConnection = new SqlConnection(ConfigurationSettings.AppSettings["connectionString"]); 
        SqlCommand myCommand = new SqlCommand("GetMenuItems", myConnection); 
        myCommand.CommandType = CommandType.StoredProcedure;// и получаем данные 
        myConnection.Open(); 
        SqlDataReader reader = myCommand.ExecuteReader(CommandBehavior.CloseConnection); 
        return reader; 
      } 
      public SqlDataReader GetSubMenuItems(int parentTab) 
      { 
        // создаем соединение (connectionString берем из Web.config) 
        SqlConnection myConnection = new SqlConnection(ConfigurationSettings.AppSettings["connectionString"]); 
        SqlCommand myCommand = new SqlCommand("GetSubMenuItems", myConnection); 
        // добавляем параметр - № родительской закладки 
        SqlParameter parameterParentTab = new SqlParameter("@ParentTab", SqlDbType.Int, 4); 
        parameterParentTab.Value = parentTab; 
        myCommand.Parameters.Add(parameterParentTab); 
        myCommand.CommandType = CommandType.StoredProcedure; 
        // и получаем данные 
        myConnection.Open(); 
        SqlDataReader reader = myCommand.ExecuteReader(CommandBehavior.CloseConnection); 
        return reader; 
      } 
    } 
  } 

Примечание: для тех, кто не знает, как использовать Web.config для хранения строки соединения, приведу пример:

  <appSettings>
    <!-- строка соединения с базой -->
    <add key="ConnectionString" value="server=localhost;database=TabList;uid=<Ваш_логин>;password=<Ваш_пароль>;" /> 
  </appSettings>

Теперь создадим в проекте новый пользовательский элемент управления и назовем его TabList. В файле TabList.ascx напишем следующее:

  <%@ Control Language="c#" AutoEventWireup="false" Codebehind="TabList.ascx.cs" Inherits="Daenur.TabList.TabList" 
TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%> 
  <table id="menuTable" height="*" cellSpacing="0" cellPadding="0" width="*" border="1" runat="server"> 
  </table> 
  <script language="javascript" type="text/javascript"> 
  var currentSubMenu = null; 
  var currentSubMenuNum = 0; 
  var closeTimer = null; 
  function openSubMenu(num) 
  { 
    var subMenu = document.getElementById("TabList_subMenu" + num); 
    if (subMenu != null) 
    { 
      cancelCloseTime(); 
      subMenu.style.display=""; 
      if ((currentSubMenu != null) && (currentSubMenuNum != num)) 
      { 
        currentSubMenu.style.display="none"; 
      } 
      currentSubMenu = subMenu; 
      currentSubMenuNum = num; 
    } 
  } 
  function closeTime() 
  { 
    closeTimer = window.setTimeout(closeMenu, 1000); 
  } 
  function cancelCloseTime() 
  { 
    if (closeTimer != null) 
    { 
      window.clearTimeout(closeTimer); 
      closeTimer = null; 
    } 
  } 
  function closeMenu() 
  { 
    if (currentSubMenu != null) 
    { 
      currentSubMenu.style.display="none"; 
      currentSubMenu = null; 
      currentSubMenuNum = 0; 
    } 
  } 
  document.onclick = closeMenu; 
  </script>

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

Файл с кодом (TabList.cs) выглядит так:

  namespace Daenur.TabList 
  { 
    using System; 
    using System.Data; 
    using System.Data.SqlClient; 
    using System.Web; 
    using System.Web.UI; 
    using System.Web.UI.HtmlControls; 
    /// <summary> 
    /// Summary description for TabList. 
    /// </summary> 
    // Направление меню (горизонтальное или вертикальное) 
    public enum repeatDirection{Horizontal = 0, Vertical}; 
    public abstract class TabList : System.Web.UI.UserControl 
    { 
      protected System.Web.UI.HtmlControls.HtmlTable menuTable; 
      private DataSource data = new DataSource();// источник данных 
      public repeatDirection RepeatDirection; // направление меню 
      private void Page_Load(object sender, System.EventArgs e) 
      {
        // Put user code to initialize the page here 
        DataBind(); 
      } 
      public override void DataBind() 
      {
      // получаем все закладки 
        SqlDataReader menuItems = data.GetMenuItems();// если меню горизонтальное 
        if (RepeatDirection == repeatDirection.Horizontal) 
        {
          // то формируем строку в нашей таблице 
          HtmlTableRow tr = new HtmlTableRow(); 
          tr.ID = "menu"; 
          tr.Attributes.Add("runat", "server"); 
          while (menuItems.Read()) 
          { 
            HtmlTableCell td = new HtmlTableCell(); 
            td.ID = "menuItem" + menuItems["TabOrder"]; 
            // создаем код закладки - ссылки
            // (здесь: onmouseout и onmouseover - события, обработчики которых находятся в скрипте) 
            string HtmlText = @"<nobr>   <a onmouseout=""closeTime()"" onmouseover=""openSubMenu(" + 
    menuItems["TabOrder"] + @")"" href=""" + menuItems["TabOrder"] + @"""> Tab" + 
    menuItems["TabOrder"] + " </a>   </nobr>"; 
            td.Controls.Add(new LiteralControl(HtmlText)); 
            // для каждой закладки создаем свою таблицу - подменю 
            td.Controls.Add(SubMenu((int) menuItems["TabOrder"])); 
            tr.Controls.Add(td); 
          } 
          menuTable.Controls.Add(tr); 
        } 
        else // RepeatDirection.Vertical 
        {
          // иначе формируем столбец 
          // (все остальное аналогично) 
          while (menuItems.Read()) 
          { 
            HtmlTableRow tr = new HtmlTableRow(); 
            tr.ID = "menu"; 
            tr.Attributes.Add("runat", "server"); 
            HtmlTableCell td = new HtmlTableCell(); 
            td.ID = "menuItem" + menuItems["TabOrder"]; 
            string HtmlText = @"  <a onmouseout=""closeTime()"" onmouseover=""openSubMenu(" + 
    menuItems["TabOrder"] + @")"" href=""" + menuItems["TabOrder"] + @"""> Tab" + 
    menuItems["TabOrder"] + " </a>  "; 
            td.Controls.Add(new LiteralControl(HtmlText)); 
            td.Controls.Add(SubMenu((int) menuItems["TabOrder"])); 
            tr.Controls.Add(td); 
            menuTable.Controls.Add(tr); 
          } 
        } 
      } 
      /// <summary> 
      ///   Функция, создающая подменю для нужной закладки 
      /// </summary> 
      private HtmlTable SubMenu(int tabOrder) 
      {
        // получаем все закладки для подменю 
        SqlDataReader subMenuItems = data.GetSubMenuItems(tabOrder);
        // создаем таблицу подменю 
        HtmlTable tbl = new HtmlTable(); 
        tbl.ID = "subMenu" + tabOrder.ToString(); 
        tbl.Style.Add("display", "none");// скрыта по умолчанию 
        tbl.Style.Add("position", "absolute");// появляется поверх всего 
  //    tbl.Style.Add("filter", "alpha (opacity=75)"); // прозрачность 
        tbl.Attributes.Add("cellSpacing", "0"); 
        tbl.Attributes.Add("cellPadding", "0"); 
        tbl.Attributes.Add("width", "160px"); 
        tbl.Attributes.Add("border", "1"); 
        tbl.Attributes.Add("bgcolor", "white");
        // назначаем обработчики событий 
        tbl.Attributes.Add("onmouseover", "cancelCloseTime()");// при наведении курсора 
        tbl.Attributes.Add("onmouseout", "closeTime()");// при выходе за пределы подменю 
        // формируем столбец, состоящий из ссылок 
        while (subMenuItems.Read()) 
        { 
          HtmlTableRow tr = new HtmlTableRow(); 
          HtmlTableCell td = new HtmlTableCell(); 
          td.InnerHtml = @"  <a href=""" + tabOrder + "-" + subMenuItems["TabOrder"] + @"""> SubTab" +  
    tabOrder + "-" + subMenuItems["TabOrder"] + "</a>  "; 
          tr.Cells.Add(td); 
          tbl.Controls.Add(tr); 
        } 
        return tbl;// возвращаем готовое подменю 
      } 
      #region Web Form Designer generated code 
      override protected void OnInit(EventArgs e) 
      {
  		//
		// CODEGEN: This call is required by the ASP.NET Web Form Designer.
		//
        InitializeComponent(); 
        base.OnInit(e); 
      } 
      /// <summary> 
      /// Required method for Designer support - do not modify 
      /// the contents of this method with the code editor. 
      /// </summary>
      private void InitializeComponent() 
      { 
        this.Load += new System.EventHandler(this.Page_Load); 
      } 
      #endregion 
    } 
  } 

Для тестирования нашего меню необходима HTML страница, содержащая наш элемент. Вот HTML код основной формы:

  <%@ Register TagPrefix="TabListControl" TagName="TabList" Src="TabList.ascx" %> 
  <%@ Page language="c#" Codebehind="Default.aspx.cs" AutoEventWireup="false" Inherits="Daenur.TabList.DefaultForm" %> 
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > 
  <HTML> 
   <HEAD> 
    <title>DefaultForm</title> 
   </HEAD> 
   <body MS_POSITIONING="GridLayout"> 
    <TABLE height="523" cellSpacing="0" cellPadding="0" width="174" border="0" ms_2d_layout="TRUE"> 
     <TR vAlign="top"> 
      <TD width="174" height="523"> 
       <form id="DefaultForm" name="DefaultForm" action="Default.aspx" method="post"> 
        <TABLE height="157" cellSpacing="0" cellPadding="0" width="511" border="0" ms_2d_layout="TRUE"> 
         <TR vAlign="top"> 
          <TD width="10" height="15"></TD> 
          <TD width="501"></TD> 
         </TR> 
         <TR vAlign="top"> 
          <TD height="142"></TD> 
          <TD> 
           <table height="141" cellSpacing="0" cellPadding="0" width="500"> 
            <tr> 
             <td width="20"></td> 
             <td width="*">
               <TABLISTCONTROL:TABLIST id="TabList" runat="server" RepeatDirection="Horizontal"></TABLISTCONTROL:TABLIST>
             </td> 
             <td width="20"></td> 
            </tr> 
            <tr> 
             <td width="20"></td> 
             <td width="*"></td> 
             <td width="20"> 
             </td> 
            </tr> 
           </table> 
          </TD> 
         </TR> 
        </TABLE> 
       </form> 
      </TD> 
     </TR> 
    </TABLE> 
   </body> 
  </HTML> 

Здесь все просто. Мы создали на форме таблицу и в одну из ее ячеек поместили наш элемент TabList.

Таким образом, получаем само меню в виде таблицы со строкой или столбцом  элементов в зависимости от заданного направления и скрытые таблицы - подменю. Видимыми их делает выполнение скрипта при наведении курсора.

Кстати, чтобы поменять направление меню на горизонтальное, достаточно исправить строку в файле Default.aspx:

RepeatDirection="Horizontal" на RepeatDirection="Vertical"

В результате:

Заключение

Как видите, все довольно просто (а Вы как хотели :)). Я показал, как можно расширить функциональность одностраничного портала, похожего на IBuySpy. Извиняюсь за возможные недочеты. В этом примере показана только суть. Остальное Вы сможете легко реализовать сами. Например, можно прикрутить сюда какую-нибудь графику или просто добавить новые свойства вроде цвета фона. Успехов в изучении новых технологий!

 

Ссылки по теме


 Распечатать »
 Правила публикации »
  Обсудить материал в конференции Дискуссии и обсуждения общего плана »
Написать редактору 
 Рекомендовать » Дата публикации: 20.08.2009 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Kerio Connect - Server (incl 5 users, 1 yr SWM)
Allround Automation PL/SQL Developer - Unlimited license
Quest Software. TOAD for Oracle Edition
SmartBear QAComplete Concurrent User Subscription License - On Premise (1 Year Subscription)
Allround Automation PL/SQL Developer Single user license
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
eManual - электронные книги и техническая документация
3D и виртуальная реальность. Все о Macromedia Flash MX.
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
Обсуждения в форумах
Подключение JavaScript (305)
Всем привет! Я подключаю JavaScript нижеприведенным образом. Код: <script...
 
Разработка устройств на микроконтроллерах (1)
Профессиональный программист. Основная специализация: МИКРОКОНТРОЛЛЕРЫ, АССЕМБЛЕР для любых...
 
Пишу программы на заказ профессионально (2921)
Пишу программы на заказ на языках Pascal (численные методы, списки, деревья, прерывания) под...
 
Как восстановить рабочий стол? Помогите срочно надо! (3)
Windows 7 максимальная. В учетной записи сменила пароль и выключила комп, после включения...
 
Пять возможностей Windows, о которых вы могли не знать (5)
пыщпыщ
 
 
 



    
rambler's top100 Rambler's Top100