Hướng dẫn xây dựng Active Menu với Asp.net - SQL Server Menu dạng Active Menu rất phổ biến trên các website hiện nay, Nó vừa giúp ta tiết kiệm không gian cho trang web vừa tạo được tính trực quan cao, nhìn vào đó nó chỉ dẫn cho người đọc biết họ đang ở chuyên mục nào của website. Đây cũng là vấn đề khá nhiều bạn quan tâm nên trong bài viết này tôi hướng dẫn bạn xây dựng một Active Menu với Asp.net - SQL Server.
DEMO Để thực hiện điều này đa số các bạn sẽ dùng Jquery hay javascript nhưng với tôi
thích lập trình trên SQL nên tôi sẽ hướng dẫn bạn thực hiện nó trong một Store
SQL là chính còn hiển thị lên trình duyệt chỉ cần gọi Store này là được.
Để thực hiện như demo trước tiên ta cần tạo menu dạng Tab với CSS như sau
#taskbar{height:33px; width:100%;
top:0;left:0;position:fixed;bottom:auto;
z-index:9999999; background:url(images/bg-taskbar.gif) repeat-x 0 0;
}
#taskbar a{text-decoration:none;}
.taskbar{width:990px;margin:0 auto;}
.taskbar-sort li{float:left;list-style:none;margin-top:5px;}
.taskbar-sort li a, .taskbar-sort li a span{height:28px;display:block;float:left;}
.taskbar-sort li a{padding-left:10px;color:#eee;line-height:28px;}
.taskbar-sort li a span{padding-right:10px;}
.taskbar-sort li a.active, .taskbar-sort li a:hover{color:#444;text-decoration:none;
background:url(images/bg-taskbar-active.gif) no-repeat 0 0;
}
.taskbar-sort li a.active{color:#333;font-weight:bold;}
.taskbar-sort li a.active span, .taskbar-sort li a:hover span{
background:url(images/bg-taskbar-active.gif) no-repeat 100% 0;
}
.taskbar-sort li a.active .icon-tasbar-nl, .taskbar-sort li a:hover .icon-tasbar-nl{
background:url(images/icon-nl-taskbar-active.gif) no-repeat 0 0;
}
.taskbar-sort li a.active .icon-tasbar-pp, .taskbar-sort li a:hover .icon-tasbar-pp{
background:url(images/icon-pp.png) no-repeat 0 0;
}
Trong css trên ta cố định ở trên cùng của trang và khi cuộn trang thì menu
này vẫn không bị cuộn bằng các thuộc tính
top:0;left:0;position:fixed;bottom:auto; Nếu không thích diều này bạn có
thể bỏ các thuộc tính này.
Code html dạng Tab có dạng như sau:
<div id="taskbar">
<div class="taskbar">
<div class="taskbar-sort">
<ul>
<li><a href="link1" class="active" ><span>Tên link1</span></a></li>
<li><a href="link2" ><span>Tên Link2</span></a></li>
<li><a href="..." ><span>...</span></a></li>
</ul>
</div>
</div>
</div>
Giờ ta sẽ dựa vào cấu trúc trên để lấy dữ liệu trong SQL. Và mỗi khi ta chọn
một Tab nào đó thì sẽ cần liệt kê danh sách các cấp con của Tab đó hiển thị dạng
SubMenu ngang, Mỗi khi chọn một menu trong menu con này thì ta sẽ active để đánh
dấu cho người xem biết họ đang xem ở chuyên mục nào. Giả sử tôi có bảng
TB_Categore được phân cấp bằng trường ParentID (Ở cuối bài viết tôi sẽ cập nhật
link để bạn download cơ sở dữ liệu này làm minh họa) khi đó ứng với ParentID=0
tương đương với Tab của bài viết (Cấu chúc CSDL của bạn có thể khác thì bạn sẽ
thay đổi cho phù hợp nhé).
Chúng ta sẽ phân tích trước khi viết thủ tục như sau: Ban đầu khi vào trang
chủ ta cần tạo thêm một Tab là Trang chủ và Active Tab này. Khi một Tab được
chọn ta cần active tab này và list ra các chuyên mục con của tab này (ta sẽ dùng
vòng lặp để thực hiện), các tab khác sẽ không được active. Khi ta chọn một
chuyên mục con thì chuyên mục này sẽ được đánh dấu cho người dùng biết đang ở
chuyên mục nào. Với phân tích trên tôi đã viết thủ tục SQL như sau:
CREATE PROCEDURE TB_Category_GetMenu_Link
@TabID int,
@CateID int
AS
BEGIN
DECLARE @SQL nvarchar(4000), @SQLCate nvarchar(4000)
SET @SQL='' SET @SQLCate=''
DECLARE @Count int, @idCate int, @CateName nvarchar(150)
-- Khai báo mở khối Tab với mặc định được Active là trang chủ nếu TabID=0
SET @SQL=@SQL+'
<div id="taskbar"><div class="taskbar"><div class="taskbar-sort"><ul>'
IF(@TabID=0)
SET @SQL=@SQL+N'<li><a href="/" class="active"><span>TRANG CHỦ</span></a></li>'
ELSE
SET @SQL=@SQL+N'<li><a href="/"><span>TRANG CHỦ</span></a></li>'
-- Khai báo 1 bản tạm
DECLARE @_Table_Temp TABLE
(
[id] [int] IDENTITY (1, 1) NOT NULL,
CateID int,
CateName nvarchar(150) NULL
)
-- Dùng vòng lặp duyệt các Tab (ParentID=0)
INSERT INTO @_Table_Temp(CateID, CateName)
Select tc.CateID, tc.CateName FROM TB_Category tc WHERE tc.ParentID=0 AND tc.Status=1
DECLARE @CurrentRow int
DECLARE @MaxRow int
SELECT @MaxRow = isnull(Max([id]),0) FROM @_Table_Temp
SET @CurrentRow = 1
WHILE @CurrentRow <=@MaxRow
BEGIN
SELECT
@idCate=tt.CateID,
@CateName=tt.CateName
FROM @_Table_Temp tt
WHERE [id] = @CurrentRow
-- Nếu đang chọn một Tab thì đặt class là active,
IF(@TabID=@idCate)
SET @SQL=@SQL+'
<li>
<a href="?tabid='+cast(@idCate AS varchar(10))+'" class="active"><span>'+@CateName+'</span></a>
</li>'
ELSE
-- Ngược lại để chế độ bìn thường
SET @SQL=@SQL+'
<li>
<a href="?tabid='+cast(@idCate AS varchar(10))+'"><span>'+@CateName+'</span></a>
</li>'
SET @CurrentRow = @CurrentRow + 1
END
-- Kết thúc vòng lặp - Đóng khối Tab
SET @SQL=@SQL+'</ul></div></div></div>'
-- Kiểm tra điều kiện nếu đã chọn một Tab thì truy vấn các chuyên mục con
IF @TabID>0
BEGIN
DECLARE @CateName2 Nvarchar(200), @idCate2 int
-- Nếu Có chọn một chuyên mục con khi đó chuyên mục được chọn sẽ được Active, các chuyên mục khác không active
IF @CateID>0
BEGIN
SET @SQLCate=@SQLCate+'<div id="cateLeadMenu">'
DECLARE Cate_Cursor CURSOR FOR
SELECT tc.CateID, tc.CateName
FROM TB_Category tc WHERE tc.ParentID=@TabID ORDER BY tc.Decen
OPEN Cate_Cursor
FETCH NEXT FROM Cate_Cursor INTO @idCate2, @CateName2
WHILE @@FETCH_STATUS = 0
BEGIN
IF @CateID=@idCate2
BEGIN
SET @SQLCate=@SQLCate+'
<a href="?tabid='+cast(@TabID AS varchar(10))+'&cateid='+cast(@idCate2 AS varchar(10))+'" class="cateactive">'+@CateName2+'</a>'
END
ELSE
SET @SQLCate=@SQLCate+'
<a href="?tabid='+cast(@TabID AS varchar(10))+'&cateid='+cast(@idCate2 AS varchar(10))+'">'+@CateName2+'</a>'
FETCH NEXT FROM Cate_Cursor INTO @idCate2, @CateName2
END
CLOSE Cate_Cursor
DEALLOCATE Cate_Cursor
SET @SQLCate=@SQLCate+'</div>'
END
ELSE
-- Nếu không có chuyên mục con nào được chọn thì sẽ là không active
BEGIN
SET @SQLCate=@SQLCate+'<div id="cateLeadMenu">'
DECLARE Cate_Cursor CURSOR FOR
SELECT tc.CateID, tc.CateName
FROM TB_Category tc WHERE tc.ParentID=@TabID ORDER BY tc.Decen
OPEN Cate_Cursor
FETCH NEXT FROM Cate_Cursor INTO @idCate2, @CateName2
WHILE @@FETCH_STATUS = 0
BEGIN
IF @CateID=@idCate2
BEGIN
SET @SQLCate=@SQLCate+'
<a href="?tabid='+cast(@TabID AS varchar(10))+'&cateid='+cast(@idCate2 AS varchar(10))+'" class="cateactive" >'+@CateName2+'</a>'
END
ELSE
SET @SQLCate=@SQLCate+'
<a href="?tabid='+cast(@TabID AS varchar(10))+'&cateid='+cast(@idCate2 AS varchar(10))+'" >'+@CateName2+'</a>'
FETCH NEXT FROM Cate_Cursor INTO @idCate2, @CateName2
END
CLOSE Cate_Cursor
DEALLOCATE Cate_Cursor
SET @SQLCate=@SQLCate+'</div>'
END
END
Select (@SQL+@SQLCate) AS Links
END
Kết quả của thủ tục trên là chuỗi html hiển thị toàn bộ menu ta cần lên trình
duyệt ứng với các giá trị khác nhau của TabID và CateID (request được).
Giờ trong trang asp.net thì đơn giản rồi chúng ta cần có thêm các stylesheet
và một Label để hiển thị:
<style>
#cateLeadMenu {width:978px; margin:0px auto;padding:40px 0px 3px 10px;
margin-top:0px; font-weight:bold; color:#800000; background-color:White;}
#cateLeadMenu a{ color:#333333; padding:0px 8px 3px 0px; text-decoration:none;}
#cateLeadMenu a:hover{ color:#CC0000;}
#cateLeadMenu .cateactive{color:#CC0000; text-decoration:underline;}
</style>
///////////////////////
<asp:Label ID="lblMenu" runat="server" />
Trong code ta chỉ cần viết hàm thực thi hàm và hiển thị dữ liệu
private int tabid = 0, cateid = 0;
protected void Page_Load(object sender, EventArgs e)
{
tabid = (Request.QueryString["tabid"] != null) ? int.Parse("0" + Request.QueryString["tabid"].ToString()) : 0;
cateid = (Request.QueryString["cateid"] != null) ? int.Parse("0" + Request.QueryString["cateid"].ToString()) : 0;
string SQL = "EXEC TB_Category_GetMenu_Link " + tabid.ToString() + "," + cateid.ToString() + "";
DataTable dtb = QueryToDataTable(SQL);
if (dtb.Rows.Count > 0)
{
lblMenu.Text = dtb.Rows[0][0].ToString();
}
}
private DataTable QueryToDataTable(string strSQL)
{
DataTable dtbTmp = new DataTable();
string connString = @"
Server =.\SQL2005;Initial Catalog=Clip_Backup;User ID=sa;Password=***";
SqlConnection conn = new SqlConnection(connString);
try
{
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(strSQL, conn);
DataSet ds = new DataSet();
da.Fill(ds, "GetData");
dtbTmp = ds.Tables[0];
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
conn.Close();
}
return dtbTmp;
}
Các bạn quan tâm có thể thực hiện, nếu có vướng mắc có thể comment bên dưới (nhớ
có dấu tiếng việt tôi mới nhận được) chúng ta sẽ trao đổi thêm
|