如何循环遍历 div 以重置链接的委托?

How to loop through the div to reset the delegate of the links in?

如果我有这样的方法来动态绘制我的侧边菜单:

private void DrawSideMenu()
{

    LinkButton x;
    TaskDTO TaskList = new TaskDTO();
    List<TaskDTO> List =   TaskList.DrawMenu(int.Parse(Session["emp"].ToString()));

    HtmlGenericControl myDIV = new HtmlGenericControl("div");
    myDIV.ID = "menu8";
    HtmlGenericControl myOrderedList = new HtmlGenericControl("ul");//css clss for <ul>
    myOrderedList.ID = "orderedList";
    myOrderedList.Attributes.Add("class", "task");
    HtmlGenericControl listItem1;
    string count = "";
    foreach (TaskDTO i in List)
    {
        count = AdjustMenuCount1(i.TaskCode);
        x = new LinkButton();
        x.ID = i.TaskCode.ToString();
        x.Text = i.TaskName + "&nbsp; &nbsp;" + count;
        x.Click += new EventHandler(TaskC);
        x.Style["FONT-FAMILY"] = "tahoma";
        listItem1 = new HtmlGenericControl("li");
        listItem1.Attributes.Add("class", "normal");
        if (count != "0")
        {
            listItem1.Controls.Add(x);
            myOrderedList.Controls.Add(listItem1);
        }
    }
    myDIV.Controls.Add(myOrderedList);
    MenuTD.Controls.Add(myDIV);
    Session["SideMenu"] = myDIV;//Save to redraw when page postbacks
}

此方法需要很长时间来绘制我的 menu.so 我在 (!IsPostBack) 中调用了一次并将其保存在会话中以便我可以像那样重绘它:

MenuTD.Controls.Add( ((System.Web.UI.Control)(Session["SideMenu"])));

它重绘成功但是当我点击任何 link 它没有触发事件因为我认为不可能在会话中保存 x.Click += new EventHandler(TaskC); 所以我想知道如何遍历我的会话内容以重置我的 link 的代表?

这个想法行不通,因为 if you're not wiring up the Event Handler every time the page is loaded, it won't run.

如果我们回到原来的问题,你说它很慢。在运行时创建控件不会很慢,这很可能是您创建项目列表的方式:

List<TaskDTO> List = TaskList.DrawMenu(int.Parse(Session["emp"].ToString()));

与其存储完整的菜单,不如尝试存储在仅会话列表中,并像往常一样创建所有控件。如果仅在一页上需要菜单,则使用 ViewState 而不是 Session.

更改整个代码也很有意义,因为目前您在代码中硬编码了所有样式和布局设置。在 aspx 中创建所有布局 (div, ul, li),在 css 中移动所有样式(例如,您使用 "task" class 但仍然设置 "tahoma"在代码中)。这将简化代码并带来更大的灵活性。

List<TaskDTO> List = null;

void Page_Load(object sender, EventArgs e)
{
    if (ViewState["List"] != null) {
        List = (List<TaskDTO>)ViewState["List"];
    } else {
       // ArrayList isn't in view state, so we need to load it from scratch.
        List = TaskList.DrawMenu(int.Parse(Session["emp"].ToString()));
    }

    // Code to create menu, e.g. 
    if (!Page.IsPosBack) {
        Repeater1.DataSource = List;
        Repeater1.DataBind();
    }
}

void Page_PreRender(object sender, EventArgs e)
{
    // Save PageArrayList before the page is rendered.
    ViewState.Add("List", List);
} 
...

<ul id="orderedList">
    <asp:Repeater ID="Repeater1" runat="server">
        <ItemTemplate>
            <li><%# Eval("TaskName") %></li>
        </ItemTemplate>
    </asp:Repeater>
</ul>

也许将它保存在应用程序级别,这样它只构建一次,然后只需将菜单放入一个对象并循环遍历它以重新添加点击。

恐怕要使其正常工作,您将不得不在每个 Page_Load.

上重新绑定 Click 处理程序

根据您的代码,假设您的 TaskC 可用,您可以使用此方法:

private void RebindMenuHandlers() {

    if(Session["SideMenu"] == null)
        return; // Your menu has not been built yet

    var menu = ((System.Web.UI.Control)(Session["SideMenu"]));

    var orderedList = menu.Controls[0];

    foreach(var listItem in orderedList){

        foreach(var control in listItem){
            var linkButton = control as LinkButton;
            if(linkButton != null){
                linkButton.Click += new EventHandler(TaskC);
            }       
        }
    }
}

然后在您的 Page_Load 活动中调用它:

void Page_Load(object sender, EventArgs e)
{
    RebindMenuHandlers();
    // .... etc
}

我只是在这里直接输入了这个,所以请原谅任何愚蠢的编译错误,这应该足以给你一个大概的想法。希望对您有所帮助。