C# 动态创建 LinkButton 命令事件处理程序

3
我这里有一个奇怪的情况...我有一个System.Web.UI.WebControls.WebParts.EditorPart类。它会呈现一个“搜索”按钮,当您单击此按钮时,它的clickHandler方法会进行数据库搜索,并动态创建每一行的LinkButton,设置CommandName和CommandArgument属性并添加CommandEventHandler方法,然后将LinkButton控件添加到页面中。
问题是,当您单击LinkButton时,它的CommandEventHandler方法从未被调用,看起来页面只是回到了原始“搜索”按钮按下之前的状态。
我看到有人说需要在OnLoad()或其他早期方法中添加事件处理程序,但我的LinkButtons甚至直到用户告诉我们要搜索什么并点击“搜索”按钮才被创建...您有什么解决方法吗?
谢谢!
4个回答

3
这是我最喜欢的技巧 :)
我们的场景是先呈现一个控件。然后使用用户的一些输入,呈现更多的控件并使它们响应事件。
关键在于状态 - 您需要知道控件在PostBack时的状态 - 因此我们使用ViewState。问题变成了鸡生蛋或蛋生鸡的问题; ViewState在LoadViewState()调用之后才可用,但您必须在该调用之前创建控件,以便正确触发事件。
诀窍是覆盖LoadViewState()SaveViewState(),以便我们可以控制事情。
(请注意,下面的代码粗略,仅凭记忆,并可能存在问题)
private string searchQuery = null;

private void SearchButton(object sender, EventArgs e)
{
    searchQuery = searchBox.Text;
    var results = DataLayer.PerformSearch(searchQuery);
    CreateLinkButtonControls(results);
}

// We save both the base state object, plus our query string.  Everything here must be serializable.
protected override object SaveViewState()
{
    object baseState = base.SaveViewState();
    return new object[] { baseState, searchQuery };
}

// The parameter to this method is the exact object we returned from SaveViewState().
protected override void LoadViewState(object savedState)
{
    object[] stateArray = (object[])savedState;

    searchQuery = stateArray[1] as string;

    // Re-run the query
    var results = DataLayer.PerformSearch(searchQuery);

    // Re-create the exact same control tree as at the point of SaveViewState above.  It must be the same otherwise things will break.
    CreateLinkButtonControls(results);

    // Very important - load the rest of the ViewState, including our controls above.
    base.LoadViewState(stateArray[0]);
}

那看起来像是个很酷的技巧,虽然我还没有尝试过(这个项目被搁置了),但它看起来应该有效。现在我们终于在这个环境中安装了3.5版本,你可能只需将搜索按钮放在UpdatePanel中,并使用部分页面回发来完成所有操作。 - spdevsolutions

1

您需要在onload事件中重新添加动态创建的控件,以便它们可以在页面层次结构中,并触发其事件。


问题在于在运行查询之前我不知道需要创建多少个控件...唯一的解决方案是在createchildcontrols中也执行查询吗? - spdevsolutions

0
 LinkButton link= new LinkButton();
 link.Command +=new CommandEventHandler(LinkButton1_Command);

 protected void LinkButton1_Command(object sender, CommandEventArgs e)
{
    try
    {
        System.Threading.Thread.Sleep(300);
        if (e.CommandName == "link")
        {
           //////////
        }
    }
    catch
    {

    }
}

-1
我刚想到的一个不太正规的方法是创建与真实按钮相同ID的虚拟LinkButtons。 假设您要在Pre_Render(太晚了)中创建一个LinkButton“foo”,那么也请在Page_Load中创建一个虚拟的foo:
        var link = new LinkButton();
        link.ID = "foo";
        link.Click += fooEventHandler;
        dummyButtons.Controls.Add(link);

(其中“dummyButtons”只是页面上设置为不可见的占位符。)虽然不太美观,但它能正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接