ASP.NET自定义控件:何时调用LoadPostData()?

Dav*_*vid 7 asp.net viewstate postback custom-controls postdata

我开发了一个扩展ListBox的自定义控件.这个想法是控件"记住"对客户端发生的元素的修改,例如由于AJAX请求.

它的工作方式是控件还呈现隐藏的输入,并且AJAX请求的结果存储在隐藏的输入中.这是回发的,控件的LoadPostData()方法查找隐藏的输入,如果隐藏的输入有数据,则从中创建ListItem集合.

只要用户从列表框中进行选择,这就完美地工作.如果没有,则不会调用LoadPostData()方法,因此不会创建新的ListItem集合.(我已经使用调试器建立了这个.)

我假设只有在POST数据集合包含与控件的UniqueID相对应的数据(即HTML中的"name"属性)时才调用LoadPostData方法.如果用户尚未从列表框中进行选择,则列表框的UniqueID的后置数据中不包含任何内容,并且不会调用LoadPostData().那是对的吗?

任何人都可以建议我如何确保每次回发都调用我的自定义ListBox的LoadPostData()方法,无论用户是否进行了选择?

提前谢谢 - 我真的很喜欢这个.

大卫

Roz*_*wel 8

我有点迟到了,但是,为了将来的参考,这里是我如何完成类似的东西......

我的控件是一个使用模板的树.我正在处理的问题是如何捕获客户端对节点的扩展/折叠状态的更改.最终工作的是:

在CreateChildControls中,将隐藏字段添加到我的根控件的控件集合中.

protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
{
    ...
    _cdExpanded = new HiddenField();
    _cdExpanded.ID = "cdExpanded";
    this.Controls.Add(_cdExpanded);
    ...
}
Run Code Online (Sandbox Code Playgroud)

在OnInit调用中

protected override void OnInit(EventArgs e)
{
    ...
    Page.RegisterRequiresPostBack(this);
    ...
}
Run Code Online (Sandbox Code Playgroud)

在LoadPostData中,在post集合中查找与隐藏字段的UniqueID(而不是ClientID)匹配的值:

public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
{
    ...
    string cdExpanded = postCollection[_cdExpanded.UniqueID];
    ...
}
Run Code Online (Sandbox Code Playgroud)

在各个节点的类中,我有代码,它通过调用JavaScript函数来填充我的切换按钮的onclick事件,该函数将基本控件的ID和各个节点作为参数.

    string ToggleScript
    {
        get
        {
            return "ToggleNode('" + this.ClientID + "', '" + _TreeRoot.ClientID + "');";
        }
    }
    protected override void Render(HtmlTextWriter writer)
    {
        ...
        if (this.HasChildren)
        {
            writer.AddAttribute("onclick", ToggleScript);
        }
        ...
    }
Run Code Online (Sandbox Code Playgroud)

这使得通过getElementById找到隐藏字段相当容易:

function ToggleNode(nodeID, treeID) {
var cdExpanded = document.getElementById(treeID + "_cdExpanded");
...
}
Run Code Online (Sandbox Code Playgroud)

然后,JavaScript根据发生的事件的需要修改隐藏字段的值.当我们回到服务器时,我能够解析出该字段的内容,并在再次呈现之前根据需要修改控件状态.(注意:我实际上使用3个隐藏字段来跟踪不同的事件,但概念是相同的)

希望这对未来的其他人有所帮助......

  • OnInit正是这里缺少的 - 谢谢! (3认同)

Dav*_*vid 1

我已经确定,除非发布数据包含与控件的 UniqueID 同名的项目,否则不会调用 LoadPostData() 方法。[编辑:在 Init() 期间调用 Page.RegisterRequiresPostback 克服了这个问题。] 我可以理解为什么,但它是相当有限的。

我通过在 LoadPostData() 方法期间根本不处理它来克服这个问题。相反,我在 OnLoad() 中调用的方法中处理了它。

使用这种方法时需要记住两件事:

1) 您不再有权访问作为参数传递给 LoadPostData() 方法的 postCollection NameValueCollection 对象。这意味着您必须从 Request.Form 集合中提取发布数据,这是一项稍微困难的工作。2) 由于 OnLoad() 发生在 ViewState 处理代码之后,因此您需要在创建 ListItems 后手动设置 SelectedValue。如果不这样做,如果列表框是通过 AJAX 填充的并且用户进行了选择,则该选择将会丢失。

我希望这对将来的人有帮助。