• ExtAspNet应用技巧(十八) 编辑菜单



    界面截图

    点击编辑在新窗口中弹出编辑页面:


    注意模拟树的下拉列表,当前节点和当前节点的所有子节点都是不可选择的:


    点击“保存并关闭”则会首先保存数据,然后关闭弹出窗口,之后回发父页面并更新Grid:


    如果我修改了表单(排序由20->21),此时点击Window右上角的关闭按钮,会弹出提示框(这是ExtAspNet内置支持的特性):



    ASPX标签定义

        <ext:PageManager ID="PageManager1" AutoSizePanelID="SimpleForm1" runat="server" />
        <ext:SimpleForm ID="SimpleForm1" ShowBorder="false" ShowHeader="false" runat="server"
            BodyPadding="5px" EnableBackgroundColor="true" Title="SimpleForm">
            <Toolbars>
                <ext:Toolbar ID="Toolbar1" runat="server">
                    <Items>
                        <ext:Button ID="btnClose" SystemIcon="Close" EnablePostBack="false" runat="server"
                            Text="关闭">
                        </ext:Button>
                        <ext:ToolbarSeparator ID="ToolbarSeparator1" runat="server">
                        </ext:ToolbarSeparator>
                        <ext:Button ID="btnSaveClose" ValidateForms="SimpleForm1" SystemIcon="SaveClose"
                            OnClick="btnSaveClose_Click" runat="server" Text="保存并关闭">
                        </ext:Button>
                    </Items>
                </ext:Toolbar>
            </Toolbars>
            <Items>
                <ext:TextBox ID="tbxName" runat="server" Label="名称" Required="true" ShowRedStar="true">
                </ext:TextBox>
                <ext:TextBox ID="tbxUrl" runat="server" Label="链接" Required="true" ShowRedStar="true">
                </ext:TextBox>
                <ext:CheckBox ID="cbxShow" runat="server" Label="显示">
                </ext:CheckBox>
                <ext:NumberBox ID="tbxSortIndex" Label="排序" Required="true" ShowRedStar="true" runat="server">
                </ext:NumberBox>
                <ext:DropDownList ID="ddlParentMenu" Label="父菜单" Required="true" ShowRedStar="true" runat="server">
                </ext:DropDownList>
            </Items>
        </ext:SimpleForm>
        


    这里面的大部分技巧在上一篇文章 《ExtAspNet应用技巧(十七) - 新增菜单》 中都已经有所介绍。


    页面初始化代码

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                LoadData();
            }
        }
        private void LoadData()
        {
            btnClose.OnClientClick = ExtAspNet.ActiveWindow.GetConfirmFormModifiedClosePostBackReference();
            int menuId = GetQueryIntValue("id");
            XMenu menu = XMenu.FetchByID(menuId);
            if (menu == null)
            {
                // 参数错误,首先弹出Alert对话框然后关闭弹出窗口
                ExtAspNet.Alert.Show("参数错误!", String.Empty, ExtAspNet.ActiveWindow.GetCloseReference());
                return;
            }
            tbxName.Text = menu.Name;
            tbxUrl.Text = menu.NavigateUrl;
            tbxSortIndex.Text = menu.SortIndex.ToString();
            cbxShow.Checked = menu.Show;
            // 绑定下拉列表
            BindDDL(menu);
        }
        


    在介绍这段代码之前,我们先回忆下父页面中的Grid的编辑链接是如何定义的:

        <ext:WindowField Text="编辑" WindowID="Window1" Title="编辑" DataIFrameUrlFields="Id"
            DataIFrameUrlFormatString="~/admin/menu_edit.aspx?id={0}" Width="50px" />
        


    也就是说,当打开此编辑菜单的页面时,URL应该类似如下形式:http://localhost/appbox/admin/menu_edit.aspx?id=6

    所以,我们首先通过定义在PageBase中的GetQueryIntValue方法,获取URL中id值:

        protected string GetQueryValue(string queryKey)
        {
            return Request.QueryString[queryKey];
        }
        protected int GetQueryIntValue(string queryKey)
        {
            int queryIntValue = -1;
            try
            {
                queryIntValue = Convert.ToInt32(Request.QueryString[queryKey]);
            }
            catch (Exception)
            {
                // TODO
            }
            return queryIntValue;
        }
        



    之后再来看下这段代码:

        XMenu menu = XMenu.FetchByID(menuId);
        if (menu == null)
        {
            // 参数错误,首先弹出Alert对话框然后关闭弹出窗口
            ExtAspNet.Alert.Show("参数错误!", String.Empty, ExtAspNet.ActiveWindow.GetCloseReference());
            return;
        }
        

    我们可以把这段代码直译为,如果对应的menuId不存在,则首先弹出Alert对话框,在用户点击对话框的确认按钮后,关闭当前弹出的窗口(ActiveWindow)。
    对应的页面的效果为(是不是很酷):







    绑定下拉列表代码


    这段代码将是本章中最出彩的一段,我们要完成的功能如下(可以在后面看到对应的代码实现):
    1. 从数据库查询所有的菜单,按照SortIndex由小到大排序,生成XMenuCollection(这是SubSonic生成的数据库表映射实体类)。
    2. 通过XMenuHelper.GetMyMenuCollection静态函数将此对象转换为List<MyMenu>(内部已经计算好TreeLevel和IsTreeLeaf)。
    3. 添加根节点(所有节点的TreeLevel加一)。
    4. 设置当前节点以及当前节点的所有子节点都不可选择(这是通过ExtAspNet支持的方法来做的)。
    5. 绑定模拟树的下拉列表。
    6. 选中下拉列表中当前节点的父节点

    来看下对应的代码实现:

        private void BindDDL(XMenu menu)
        {
            XMenuCollection menus = new Select().From<XMenu>()
                .OrderAsc(XMenu.SortIndexColumn.ColumnName)
                .ExecuteAsCollection<XMenuCollection>();
            List<MyMenu> newMenus = XMenuHelper.GetMyMenuCollection(menus);
            // 所有节点的TreeLevel加一,然后添加根节点
            foreach (MyMenu myMenu in newMenus)
            {
                myMenu.TreeLevel += 1;
            }
            MyMenu rootMenu = new MyMenu();
            rootMenu.Name = "==根节点==";
            rootMenu.Id = 0;
            rootMenu.TreeLevel = 0;
            newMenus.Insert(0, rootMenu);
            // 本节点不可点击(也就是说当前节点不可能是当前节点的父节点)
            // 并且本节点的所有子节点也不可点击,你想如果当前节点跑到子节点的子节点,那么这些子节点就从树上消失了
            bool startChileNode = false;
            int currentMenuTreeLevel = 0;
            foreach (MyMenu myMenu in newMenus)
            {
                if (myMenu.Id == menu.Id)
                {
                    currentMenuTreeLevel = myMenu.TreeLevel;
                    myMenu.Enabled = false;
                    startChileNode = true;
                }
                else
                {
                    if (startChileNode)
                    {
                        if (myMenu.TreeLevel > currentMenuTreeLevel)
                        {
                            myMenu.Enabled = false;
                        }
                        else
                        {
                            startChileNode = false;
                        }
                    }
                }
            }
            // 绑定到下拉列表(启用模拟树功能和不可选择项功能)
            ddlParentMenu.EnableSimulateTree = true;
            ddlParentMenu.DataTextField = "Name";
            ddlParentMenu.DataValueField = "Id";
            ddlParentMenu.DataSimulateTreeLevelField = "TreeLevel";
            ddlParentMenu.DataEnableSelectField = "Enabled";
            ddlParentMenu.DataSource = newMenus;
            ddlParentMenu.DataBind();
            // 选中当前节点的父节点
            ddlParentMenu.SelectedValue = menu.ParentMenuId.ToString();
        }
        



    页面事件处理代码

        protected void btnSaveClose_Click(object sender, EventArgs e)
        {
            int menuId = GetQueryIntValue("id");
            XMenu menu = XMenu.FetchByID(menuId);
            menu.Name = tbxName.Text.Trim();
            menu.NavigateUrl = tbxUrl.Text.Trim();
            menu.SortIndex = Convert.ToInt32(tbxSortIndex.Text.Trim());
            menu.Show = cbxShow.Checked;
            menu.ParentMenuId = Convert.ToInt32(ddlParentMenu.SelectedValue);
            menu.Save(User.Identity.Name);
    
            ExtAspNet.Alert.Show("保存成功!", String.Empty, ExtAspNet.ActiveWindow.GetClosePostBackReference());
        }
        




    下一章,我们将会介绍如何日志管理模块。


    下载全部源代码




  • 相关阅读:
    svchost服务(DLL服务)
    Windows Pe 第三章 PE头文件-EX-相关编程-2(RVA_FOA转换)
    Windows Pe 第三章 PE头文件-EX-相关编程-2(RVA_FOA转换)
    Windows Pe 第三章 PE头文件-EX-相关编程-1(PE头内容获取)
    Windows Pe 第三章 PE头文件-EX-相关编程-1(PE头内容获取)
    Windows Pe 第三章 PE头文件(下)
    Windows Pe 第三章 PE头文件(下)
    Windows Pe 第三章 PE头文件(中)
    Windows Pe 第三章 PE头文件(中)
    Windows核心编程 第七章 线程的调度、优先级和亲缘性(下)
  • 原文地址:https://www.cnblogs.com/sanshi/p/1565894.html
Copyright © 2020-2023  润新知