Issue in creating a data driven menu in asp.net

北战南征 提交于 2019-12-25 16:48:33

问题


I am creating a data-driven dynamic menu in asp.net, using sql server 2008 R2 as my database. The parent node, and child nodes at the first level works just fine. but the child node below another child node, the application generate an exception. The c# code for my problem is as follows :

public partial class LeaveManagementSystemMasterPage : System.Web.UI.MasterPage
{
SqlConnection conn;
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        getMenu();
    }
}

private void getMenu()
{
    Connect();
    conn.Open();
    DataSet ds = new DataSet();
    DataTable dt = new DataTable();
    string sqlQuery = "select * from menu";
    SqlDataAdapter da = new SqlDataAdapter(sqlQuery, conn);
    da.Fill(ds);
    dt = ds.Tables[0];
    DataRow[] rowParent = dt.Select("ParentID=" + 0);
    DataRow[] rowChild = dt.Select("ParentID>"+0);

    //populating the first level of the menu
    foreach (DataRow dr in rowParent)
    {
        Menu1.Items.Add(new MenuItem(dr["MenuName"].ToString(),dr["MenuID"].ToString(),"",""));
    }

    //populating the children in menu
    foreach (DataRow dr in rowChild)
    {
        MenuItem child = new MenuItem(dr["MenuName"].ToString(), dr["MenuID"].ToString(), "", "");
        Menu1.FindItem(dr["ParentID"].ToString()).ChildItems.Add(child);

    }


    conn.Close();

}

public void Connect()
{
    string conStr="Data Source=HO-0000-LAP; Initial Catalog=LeaveManagementSystem; Integrated Security=true";
     conn = new SqlConnection(conStr);
}

}

And here is my table which i have designed in sqlserver 2008 :-


回答1:


The solution which i found useful for the issue was found at

Getting Menu Items from database in asp.net

And here is my source code :-

public partial class LeaveManagementSystemMasterPage : System.Web.UI.MasterPage

{ SqlConnection conn; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { getMenu(); } }

private void getMenu()
{
    Connect();
    DataSet ds = new DataSet();
    DataTable dt = new DataTable();
    string sqlQuery = "select * from menu";
    SqlDataAdapter da = new SqlDataAdapter(sqlQuery, conn);
    da.Fill(ds);
    dt = ds.Tables[0];
    AddTopMenuItems(dt);


}

private void AddTopMenuItems(DataTable menuData)
{
    DataView view = new DataView(menuData);
    view.RowFilter = "ParentID = 0";
    foreach (DataRowView rowView in view)
    {
        MenuItem topItem = new MenuItem(rowView["MenuName"].ToString(),rowView["MenuID"].ToString());
        Menu1.Items.Add(topItem);
        AddChildItems(menuData, topItem);
    }

}

private void AddChildItems(DataTable menuData, MenuItem parentMenuItem)
{
    DataView view = new DataView(menuData);
    view.RowFilter = "ParentID = " + parentMenuItem.Value;

    foreach(DataRowView rowView in view)
    {
        MenuItem childItem = new MenuItem(rowView["MenuName"].ToString(), rowView["MenuID"].ToString());
        parentMenuItem.ChildItems.Add(childItem);
        AddChildItems(menuData, childItem);
    }

}

public void Connect()
{
    string conStr="Data Source=HO-0000-LAP; Initial Catalog=LeaveManagementSystem; Integrated Security=true";
     conn = new SqlConnection(conStr);
}

}




回答2:


Going to venture a guess here and say it has to do with order of creation of the 3rd level child items.

You explicitly add parent items to the menu from rowParent collection, then you add "the rest". The problem is that when you start the 2nd for loop for adding children, you are relying on the order of the items to be such that higher level items are added first. This is not guaranteed.

So what may be happening (if you post the exception we can confirm) is like this

After the foreach loop (on rowParent) your menu object has all 5 parent items added

Administration (ID 1), 
Setup (ID 2)
Operations (ID 3) 
Reports (ID 4) 
Logout (ID 5)

On the 2nd foreach, for example, lets day you have 2 items, for example because this is likely where your problem is

Management ID 31, ParentID 3
Initiate Application ID 311, ParentID 31

If Management is added first, then Initiate Application will work as FindItem() will find the parent to add to.

However, if initiate Application goes first, and management has not been added yet, it will throw an error because FindItem() will fail (the item hasn't been added yet).

You can add an order by clause and order by Parent ID to ensure items get added in an order such that lower numbered parent items will be added first.

Or you can make a function and pass it the parent ID's several times over for each level, to make sure you're always adding child items to parents that have already been added. On iPad now but will add some code shortly.



来源:https://stackoverflow.com/questions/15269261/issue-in-creating-a-data-driven-menu-in-asp-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!