0

我在 asp.net 中创建一个数据驱动的动态菜单,使用 sql server 2008 R2 作为我的数据库。第一级的父节点和子节点工作得很好。但是子节点下面有另一个子节点,应用程序产生异常。我的问题的 c# 代码如下:

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);
}

}

这是我在 sqlserver 2008 中设计的表:-

菜单数据库

4

2 回答 2

1

我发现对这个问题有用的解决方案位于

从 asp.net 的数据库中获取菜单项

这是我的源代码:-

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

{ SqlConnection 连接;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);
}

}

于 2013-03-07T11:37:44.340 回答
0

在这里冒险猜测一下,它与 3 级子项的创建顺序有关。

您将父项从 rowParent 集合显式添加到菜单,然后添加“其余”。问题是,当您开始第二个 for 循环以添加子项时,您依赖于项目的顺序,以便首先添加更高级别的项目。这不能保证。

所以可能发生的事情(如果您发布我们可以确认的异常)是这样的

在 foreach 循环(在 rowParent 上)之后,您的菜单对象添加了所有 5 个父项

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

例如,在第 2 次 foreach 中,让您有 2 个项目,例如因为这可能是您的问题所在

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

如果首先添加管理,则启动应用程序将作为 FindItem() 将找到要添加的父项。

但是,如果先启动Application,并且还没有添加管理,则会抛出错误,因为FindItem()会失败(尚未添加项目)。

您可以添加 order by 子句和 order by Parent ID,以确保按顺序添加项目,以便首先添加编号较低的父项目。

或者您可以创建一个函数并将每个级别的父 ID 多次传递,以确保您始终将子项添加到已添加的父项。现在在 iPad 上,但很快会添加一些代码。

于 2013-03-07T11:23:50.630 回答