zoukankan      html  css  js  c++  java
  • ExtAspNet应用技巧(十六) 菜单管理


    界面截图

    模拟树的Grid,这个是ExtAspNet中Grid控件的一个特色哦,是不是很方便: 


    点击CheckBox自动回发,并修改数据库此条数据的状态: 


    点击删除弹出确认对话框,注意这个对话框是在父页面中弹出的: 


    通过可以按下的按钮(EnablePress)来设置简单的过滤条件: 


    点击编辑弹出窗口(这个窗口是编辑页面IFrame,会在下一章介绍),注意这个弹出窗口也是在父页面弹出的,这也是ExtAspNet的一大特色: 



    ASPX标签

        <ext:PageManager ID="PageManager1" AutoSizePanelID="Grid1" runat="server" />
        <ext:Grid ID="Grid1" runat="server" ShowBorder="false" EnableCheckBoxSelect="false"
            EnableRowNumber="true" DataKeyNames="Id" OnRowCommand="Grid1_RowCommand" Title="菜单管理">
            <Toolbars>
                <ext:Toolbar ID="Toolbar1" Position="Top" runat="server">
                    <Items>
                        <ext:Button ID="btnOnlyTwoLevelMenu" EnablePress="true" OnClick="btnOnlyTwoLevelMenu_Click"
                            runat="server" Text="仅显示一二级菜单">
                        </ext:Button>
                        <ext:ToolbarSeparator ID="ToolbarSeparator1" runat="server">
                        </ext:ToolbarSeparator>
                        <ext:Button ID="btnNoHiddenMenu" EnablePress="true" OnClick="btnNoHiddenMenu_Click"
                            runat="server" Text="不显示隐藏菜单">
                        </ext:Button>
                        <ext:ToolbarFill ID="ToolbarFill1" runat="server">
                        </ext:ToolbarFill>
                        <ext:Button ID="btnNew" runat="server" SystemIcon="New" EnablePostBack="false" Text="新增菜单">
                        </ext:Button>
                    </Items>
                </ext:Toolbar>
            </Toolbars>
            <Columns>
                <ext:BoundField DataField="Name" HeaderText="名称" DataSimulateTreeLevelField="TreeLevel"
                    Width="120px" />
                <ext:BoundField DataField="NavigateUrl" HeaderText="链接" ExpandUnusedSpace="true" />
                <ext:CheckBoxField ColumnId="cbxShow" DataField="Show" HeaderText="显示" RenderAsStaticField="false"
                    AutoPostBack="true" CommandName="Show" Width="50px" />
                <ext:BoundField DataField="SortIndex" HeaderText="排序" Width="50px" />
                <ext:WindowField Text="编辑" WindowID="Window1" Title="编辑" DataIFrameUrlFields="Id"
                    DataIFrameUrlFormatString="~/admin/menu_edit.aspx?id={0}" Width="50px" />
                <ext:LinkButtonField Text="删除" ConfirmText="确定删除此菜单?" ConfirmTarget="_parent" CommandName="Delete"
                    Width="50px" />
            </Columns>
        </ext:Grid>
        <ext:Window ID="Window1" runat="server" Height="350px" IsModal="true" Popup="false"
            Target="_parent" EnableIFrame="true" IFrameUrl="about:blank" Width="500px">
        </ext:Window>
        


    整体上来看,这个页面包括三个ExtAspNet控件:PageManager, Gird, Window。 在Grid内部,又包含了一些其他ExtAspNet控件:Toolbar, Button, ToolbarFill。

    虽然一些应用技巧在前几篇文章中已经出现过,不过有一些新的应用技巧:
    • Button的EnablePress="true",则此按钮拥有按下弹出的效果
    • ToolbarFill,用来将工具栏分隔成左右两部分
    • Button的SystemIcon="New",则此按钮前面会显示预定义的图标(SystemIcon是枚举类型,可用的还有Close, Delete, Save, Search等)
    • Grid的DataKeyNames="Id",用来定义行的主键(可以是多个,比如DataKeyNames="Id,Name"),在后台代码中可以通过DataKeys属性获取其值
    • 为Grid的每一列设置宽度,剩下的一列应用ExpandUnusedSpace="true"属性,则此列会占据所有剩余的空白空间
    • LinkButtonField的ConfirmTarget="_parent",则确认对话框在父页面弹出
    • Window的Target="_parent",用来控制此窗口在父页面弹出(这在IFrame框架中非常重要)
    • DataSimulateTreeLevelField="TreeLevel"用来实现模拟树的行为



    重定义Menu的实体类

    因为需要生成模拟树的表格,我们需要重定义从数据库表X_Menu映射过来的实体类,增加public int TreeLevel属性。

        public class MyMenu
        {
            private int id;
            private string name;
            private string imageUrl;
            private string navigateUrl;
            private bool show;
            private int parentMenuId;
            private int sortIndex;
            private int treeLevel;
            private string remark;
            public string Remark
            {
                get { return remark; }
                set { remark = value; }
            }
            public int TreeLevel
            {
                get { return treeLevel; }
                set { treeLevel = value; }
            }
            public int SortIndex
            {
                get { return sortIndex; }
                set { sortIndex = value; }
            }
            public int ParentMenuId
            {
                get { return parentMenuId; }
                set { parentMenuId = value; }
            }
            public bool Show
            {
                get { return show; }
                set { show = value; }
            }
            public string NavigateUrl
            {
                get { return navigateUrl; }
                set { navigateUrl = value; }
            }
            public string ImageUrl
            {
                get { return imageUrl; }
                set { imageUrl = value; }
            }
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
            public int Id
            {
                get { return id; }
                set { id = value; }
            }
        }
        



    页面后台代码

        public partial class menu : PageBase
        {
            private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
            #region Page_Load
            protected void Page_Load(object sender, EventArgs e)
            {
                if (!IsPostBack)
                {
                    LoadData();
                }
            }
            private void LoadData()
            {
                btnNew.OnClientClick = Window1.GetShowReference("~/admin/menu_new.aspx", "新增");
                BindGrid();
            }
            private void BindGrid()
            {
                // TODO BindGrid
            }
            #endregion
            #region Events
            protected void Grid1_RowCommand(object sender, ExtAspNet.GridCommandEventArgs e)
            {
                // TODO Grid1_RowCommand
            }
    
            protected void btnOnlyTwoLevelMenu_Click(object sender, EventArgs e)
            {
                BindGrid();
            }
            protected void btnNoHiddenMenu_Click(object sender, EventArgs e)
            {
                BindGrid();
            }
            #endregion
        }
        


    在页面第一次加载时,注册点击“新增菜单”按钮的客户端脚本。
    Window1.GetShowReference函数的第一个参数是Window中IFrame的页面地址,注意此时Window1必须设置了EnableIFrame="true"属性。


    BindGrid函数

    这个是本页面的核心函数,首先从数据库查询数据,然后经过一定的转换,最后绑定到Grid控件。
        private void BindGrid()
        {
            SqlQuery q = new Select().From<XMenu>();
            if (btnNoHiddenMenu.Pressed)
            {
                q.Where(XMenu.ShowColumn).IsEqualTo(true);
            }
            q.OrderAsc(XMenu.SortIndexColumn.ColumnName);
            XMenuCollection menus = q.ExecuteAsCollection<XMenuCollection>();
    
            List<MyMenu> newMenus = null;
            if (btnOnlyTwoLevelMenu.Pressed)
            {
                newMenus = XMenuHelper.GetMyMenuCollection(menus, 1);
            }
            else
            {
                newMenus = XMenuHelper.GetMyMenuCollection(menus);
            }
            Grid1.DataSource = newMenus;
            Grid1.DataBind();
        }
        


    这里引入了另一个静态类,用来将XMenuCollection转换为List<MyMenu>,同时计算每个菜单项的深度(MyMenu中的TreeLevel属性)。

        public class XMenuHelper
        {
            public static List<MyMenu> GetMyMenuCollection(XMenuCollection oldMenus)
            {
                return GetMyMenuCollection(oldMenus, 100);
            }
            public static List<MyMenu> GetMyMenuCollection(XMenuCollection oldMenus, int maxLevel)
            {
                List<MyMenu> newMenus = new List<MyMenu>();
                ResolveMenuCollection(oldMenus, newMenus, 0, 0, maxLevel);
                return newMenus;
            }
            private static void ResolveMenuCollection(XMenuCollection oldMenus, List<MyMenu> newMenus, int parentId, int level, int maxLevel)
            {
                foreach (XMenu menu in oldMenus)
                {
                    if (menu.ParentMenuId == parentId)
                    {
                        MyMenu myMenu = new MyMenu();
                        newMenus.Add(myMenu);
                        myMenu.TreeLevel = level;
                        myMenu.Id = menu.Id;
                        myMenu.ImageUrl = menu.ImageUrl;
                        myMenu.Name = menu.Name;
                        myMenu.NavigateUrl = menu.NavigateUrl;
                        myMenu.ParentMenuId = menu.ParentMenuId;
                        myMenu.Remark = menu.Remark;
                        myMenu.Show = menu.Show;
                        myMenu.SortIndex = menu.SortIndex;
    
                        if (level < maxLevel)
                        {
                            level++;
                            ResolveMenuCollection(oldMenus, newMenus, menu.Id, level, maxLevel);
                            level--;
                        }
                    }
                }
            }
        }
        



    Grid1_RowCommand事件处理

    在Grid1的行事件中,需要处理两种类型的行事件,分别是:
        <ext:CheckBoxField ColumnId="cbxShow" DataField="Show" HeaderText="显示" RenderAsStaticField="false"
            AutoPostBack="true" CommandName="Show" Width="50px" />
        

        <ext:LinkButtonField Text="删除" ConfirmText="确定删除此菜单?" ConfirmTarget="_parent" CommandName="Delete"
            Width="50px" />
        


        protected void Grid1_RowCommand(object sender, ExtAspNet.GridCommandEventArgs e)
        {
            int menuId = Convert.ToInt32(Grid1.DataKeys[e.RowIndex][0]);
            if (e.CommandName == "Delete")
            {
                XMenu.Delete(menuId);
                BindGrid();
            }
            else if (e.CommandName == "Show")
            {
                ExtAspNet.CheckBoxField myCheckBoxField = Grid1.Columns.FindColumnById("cbxShow") as ExtAspNet.CheckBoxField;
                bool rowChecked = myCheckBoxField.GetCheckState(e.RowIndex);
                XMenu menu = XMenu.FetchByID(menuId);
                menu.Show = rowChecked;
                menu.Save(User.Identity.Name);
                BindGrid();
            }
        }
        


    至此,整个列表页面完成。

    下一章,我们将会介绍如何在弹出的新窗口中添加菜单和编辑菜单。


    下载全部源代码



  • 相关阅读:
    <style>的scope属性
    scrollIntoView的使用
    需要学习的内容列表
    react生命周期
    JS对象-不可扩展对象、密封对象、冻结对象
    神策埋点
    Django初识
    MySQL的sql_mode模式说明及设置
    MySQL的逻辑查询语句的执行顺序
    MySQL行(记录)的详细操作
  • 原文地址:https://www.cnblogs.com/sanshi/p/1565000.html
Copyright © 2011-2022 走看看