Xây dựng Menu đa cấp với Multi Sitemap

Để tránh việc trình duyệt phải quay lại server và lấy dữ liệu từ database quá nhiều chúng ta có thể xây dựng menu đa cấp bằng cách dùng asp:Menu  sử dụng Site Map file. Bạn hãy xây dựng cho mình 1 control để sử dụng được nhiều Site map trong website của bạn. Mình sẽ hướng dẫn các bạn xây dựng để có thể sử dụng Menu đa cấp với MultiSitemap
1. Xây dựng Control menu
Bạn hãy tạo một thư mục Controls (Bạn có thể không cần tạo thư mục nhưng theo mình thì bạn nên tạo vì trong dự án của mình có thể có nhiều controls) sau đó nhấn phải chuột vào thư mục này, Chon Add New Item… tiếp theo chọn Web User Control đặt tên cho Control của bạn (ucMenuMultiSitemap.ascx)

Nội dung trong file Control (ucMenuMultiSitemap.ascx) như sau:

<asp:Menu 
    id="mnMainMeNu" 
    runat="server" 
    StaticEnableDefaultPopOutImage="False" 
    Orientation="Horizontal" 
    Height="20px"
    EnableTheming="True"
    DynamicVerticalOffset="0" 
    DynamicHorizontalOffset="0">
    <StaticMenuStyle 
        BorderStyle="Outset" 
        BorderWidth="0px" 
        CssClass="IE8Fix" 
        Height="23px"  />
    <StaticMenuItemStyle 
        CssClass="IE8Fix" 
        ForeColor="Black" 
        Height="20px"
        HorizontalPadding="7px"  />
    <DynamicMenuStyle 
        BorderStyle="Outset" 
        BorderWidth="1px" 
        CssClass="IE8Fix"  />
    <DynamicMenuItemStyle 
        CssClass="IE8Fix" 
        ForeColor="Black"
        Height="21px" 
        HorizontalPadding="7px" 
        Width="150px"  />
    <DynamicHoverStyle 
        BackColor="SteelBlue" 
        CssClass="IE8Fix" 
        ForeColor="White" 
        Height="20px"  />
    <StaticHoverStyle 
        BackColor="SteelBlue" 
        CssClass="IE8Fix" 
        ForeColor="White"  />
    <DataBindings> 
        <asp:MenuItemBinding
            DataMember="siteMapNode" 
            TextField="title"  
            NavigateUrlField="url"  /> 
    </DataBindings>
</asp:Menu>

Trong file code C# (ucMenuMultiSitemap.ascx.cs) bạn viết như sau.

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class Controls_ucMenuMultiSitemap : System.Web.UI.UserControl
{
    /// <summary>
    /// Định nghĩa các loại menu
    /// </summary>
    public enum MenuSitemap
    {
        TopMenu, BottomMenu, NotSet, LeftMenu, RightMenu
    }
    MenuSitemap eMenuToLoad = MenuSitemap.NotSet;
    public MenuSitemap MenuToLoad
    {
        get { return eMenuToLoad; }
        set { eMenuToLoad = value; }
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        mnMainMeNu.DataSource = GetMenuDataSource(eMenuToLoad, Server.MapPath("~"));
        mnMainMeNu.DataBind();
    }
    /// <summary>
    /// Lấy menu theo tùy chọn menu và tên file sitemap
    /// </summary>
    XmlDataSource GetMenuDataSource(MenuSitemap menu, string serverMapPath)
    {
        XmlDataSource objData = new XmlDataSource();
        objData.XPath = "siteMap/siteMapNode";
        switch (menu)
        {
            case MenuSitemap.TopMenu:
                objData.DataFile = serverMapPath + @"\App_Data\MenuTop.sitemap";
                break;
            case MenuSitemap.BottomMenu:
                objData.DataFile = serverMapPath + @"\App_Data\MenuBottom.sitemap";
                break;
            case MenuSitemap.LeftMenu:
                objData.DataFile = serverMapPath + @"\App_Data\MenuLeft.sitemap";
                break;
            case MenuSitemap.RightMenu:
                objData.DataFile = serverMapPath + @"\App_Data\MenuRight.sitemap";
                break;
            default:
                break;
        }
        objData.DataBind();
        return objData;
    }
}

Vậy là xong phần xây dựng Control menu

2. Sử dụng Control menu

Để sử dụng Control này trước tiên bạn cần khai báo như sau (Đặt trên thẻ <!DOCTYPE)

<%@ Register TagPrefix="hmwebmenu" TagName="MyMenu" Src="~/Controls/ucMenuMultiSitemap.ascx" %>

Sau đó trong nội dung nơi mà bạn muốn đặt menu của bạn, bạn chỉ cần sử dụng thẻ menu như sau:

<hmwebmenu:MyMenu ID="MyMenu1" runat="server" MenuToLoad="BottomMenu" />
<%--Trong thẻ trên bạn chọn MenuToload=”BottomMenu” là để menu của bạn đọc nội dung từ file MenuBottom.sitemap được khai báo trong hàm GetMenuDataSource, Nếu không muốn khai báo trong trang aspx, bạn có thể dùng codebehind để thực hiện --%>

Kết quả khi chạy như sau:

Bạn cần chú ý trong thẻ <style> bạn cần có IE8Fix để sử dụng trong menu nếu không với trình duyệt IE8 sẽ không chạy được với asp:menu.

<style>
.IE8Fix
{
    z-index: 1000;
}
</style>

Bạn có thể download source về và chạy thử. 

MultiSitemapMenu.rar (4,18 kb)

Bạn có thể thắc mắc khi lấy nội dung từ database để tạo menu đa cấp. Việc đó cũng không khó khăn. ở bài sau mình sẽ hướng dẫn cách bind dữ liệu từ database ra file.sitemap. Bạn xem hàm viết bằng SQL

Mở rộng bài này bạn có thể thực hiện việc phân quền cho ứng dụng. Ví dụ ứng dụng của bạn có 2 mức quyền là admin và User khi đó bạn cần tạo 2 file admin.sitemap và user.sitemap, còn việc phân quyền đề khi nào thì gọi các file tương ứng thì cũng không có gì khó khăn

Chúc các bạn thành công!

Chuyển đổi xâu ký tự từ TCVN3 sang Unicode C#

Trong nhiều trường hợp cần phải chuyển đổi mã từ TCVN 3 sang Unicode. Bài này giới thiệu một thuật toán đơn giản cho phép chuyển đổi một xâu ký tự từ TCVN 3 sang Unicode.  Ý tưởng của thuật toán là xây dựng hai mảng chứa các ký tự tiếng Việt có dấu cho mã TCVN 3 và Unicode. Để không phải tìm kiếm mỗi khi gặp ký tự có dấu, cần xây dựng một mảng trung gian để chuyển đổi, điều này làm giảm đáng kể thời gian chuyển đổi.

using System;
using System.Collections.Generic;
using System.Text;

class Converter {
    private static char[] tcvnchars = {
        ‘µ’, ‘¸’, ‘¶’, ‘·’, ‘¹’, 
        ‘¨’, ‘»’, ‘¾’, ‘¼’, ‘½’, ‘Æ’, 
        ‘©’, ‘Ç’, ‘Ê’, ‘È’, ‘É’, ‘Ë’, 
        ‘®’, ‘Ì’, ‘Ð’, ‘Î’, ‘Ï’, ‘Ñ’, 
        ‘ª’, ‘Ò’, ‘Õ’, ‘Ó’, ‘Ô’, ‘Ö’, 
        ‘×’, ‘Ý’, ‘Ø’, ‘Ü’, ‘Þ’, 
        ‘ß’, ‘ã’, ‘á’, ‘â’, ‘ä’, 
        ‘«’, ‘å’, ‘è’, ‘æ’, ‘ç’, ‘é’, 
        ‘¬’, ‘ê’, ‘í’, ‘ë’, ‘ì’, ‘î’, 
        ‘ï’, ‘ó’, ‘ñ’, ‘ò’, ‘ô’, 
        ‘­’, ‘õ’, ‘ø’, ‘ö’, ‘÷’, ‘ù’, 
        ‘ú’, ‘ý’, ‘û’, ‘ü’, ‘þ’, 
        ‘¡’, ‘¢’, ‘§’, ‘£’, ‘¤’, ‘¥’, ‘¦’
    };

    private static char[] unichars = {
        ‘à’, ‘á’, ‘ả’, ‘ã’, ‘ạ’, 
        ‘ă’, ‘ằ’, ‘ắ’, ‘ẳ’, ‘ẵ’, ‘ặ’, 
        ‘â’, ‘ầ’, ‘ấ’, ‘ẩ’, ‘ẫ’, ‘ậ’, 
        ‘đ’, ‘è’, ‘é’, ‘ẻ’, ‘ẽ’, ‘ẹ’, 
        ‘ê’, ‘ề’, ‘ế’, ‘ể’, ‘ễ’, ‘ệ’, 
        ‘ì’, ‘í’, ‘ỉ’, ‘ĩ’, ‘ị’, 
        ‘ò’, ‘ó’, ‘ỏ’, ‘õ’, ‘ọ’, 
        ‘ô’, ‘ồ’, ‘ố’, ‘ổ’, ‘ỗ’, ‘ộ’, 
        ‘ơ’, ‘ờ’, ‘ớ’, ‘ở’, ‘ỡ’, ‘ợ’, 
        ‘ù’, ‘ú’, ‘ủ’, ‘ũ’, ‘ụ’, 
        ‘ư’, ‘ừ’, ‘ứ’, ‘ử’, ‘ữ’, ‘ự’, 
        ‘ỳ’, ‘ý’, ‘ỷ’, ‘ỹ’, ‘ỵ’, 
        ‘Ă’, ‘Â’, ‘Đ’, ‘Ê’, ‘Ô’, ‘Ơ’, ‘Ư’
    };

    private static char[] convertTable;

    static Converter() {
        convertTable = new char[256];
        for (int i = 0; i < 256; i++)
            convertTable[i] = (char)i;
        for (int i = 0; i < tcvnchars.Length; i++)
            convertTable[tcvnchars[i]] = unichars[i];
    }

    public static string TCVN3ToUnicode(string value) {
        char[] chars = value.ToCharArray();
        for (int i = 0; i < chars.Length; i++)
            if (chars[i] < (char)256)
                chars[i] = convertTable[chars[i]];
        return new string(chars);
    }
}