【问题标题】:Prevent new render of CheckBoxList阻止 CheckBoxList 的新渲染
【发布时间】:2009-12-10 10:43:52
【问题描述】:

我有一个<asp:CheckBoxList> 在我的页面中使用RepeatLayout="Flow" 动态分配值。如果页面是第一次加载(!IsPostBack),渲染的版本类似这样;

<span children="Cat">
    <input id="ctl00_Menu_Category_0" type="checkbox" name="ctl00$Menu$Category$0"/>
    <label for="ctl00_Menu_Category_0">Cat</label>
</span>
<br/>
<span class="Cat">
    <input id="ctl00_Menu_Category_1" type="checkbox" name="ctl00$Menu$Category$1"/>
    <label for="ctl00_Menu_Category_1"> - SubCat1</label>
</span>

children 是我用于 jQuery 代码的属性,因此当用户检查 Cat 时,所有 SubCats 也会被检查。

jQuery 代码搜索所有类等于children-attribute 的&lt;span&gt;s,所以我需要维护这个jQuery 工作的结构。

但是,在我重新加载页面或点击链接之后,无论如何,列表突然看起来像这样:

<input id="ctl00_Menu_Category_0" type="checkbox" name="ctl00$Menu$Category$0"/>
<label for="ctl00_Menu_Category_0">Cat</label>
<br/>
<input id="ctl00_Menu_Category_1" type="checkbox" name="ctl00$Menu$Category$1"/>
<label for="ctl00_Menu_Category_1"> - SubCat1</label>

这怎么可能?我只将值分配给列表一次,那么为什么在 PostBack 之后重新渲染它,我该如何防止它这样做呢?

编辑

这是创建列表的代码;

// Get all available categories that are not a child of another category
DataTable categoryParents = functions.SelectSql(Resources.Data.GetCategoryParents);

// Get the child categories
foreach (DataRow parent in categoryParents.Rows)
{
    // Add the category
    ListItem parentItem = new ListItem(parent["Name"].ToString(), parent["Name"].ToString());
    parentItem.Attributes.Add("children", parent["Name"].ToString().Replace(' ', '_'));
    Category.Items.Add(parentItem);

    // For every parent category, get all its child categories
    DataTable categoryChildren = functions.SelectSql(Resources.Data.GetCategoryChildrenByParent.Replace("##PARENTID##", parent["ID"].ToString()));

    // Add the child categories after their parents
    foreach (DataRow child in categoryChildren.Rows)
    {
        ListItem item = new ListItem(" - " + child["Name"].ToString(), parent["Name"].ToString() + "\\" + child["Name"].ToString());
        item.Attributes.Add("class", parent["Name"].ToString().Replace(' ', '_'));
        Category.Items.Add(item);
    }
}
Category.DataBind();

jQuery 本身不对 HTML 做任何事情,它只是拥有在检查父项时检查子类别的功能;

$("#Category :checkbox").click(function(){
    var checked = $(this).attr("checked");
    var children = $(this).parent("span").attr("children");
    $("#Category ." + children + " :checkbox").attr("checked", checked);
});

【问题讨论】:

    标签: c# asp.net-3.5 postback rendering checkboxlist


    【解决方案1】:

    每次重新加载页面时都会呈现整个 HTML 代码。您可以通过检查IsPostBack 来防止改变这次 HTML 的呈现方式。这意味着当页面回发时,服务器不会将复选框列表与新值绑定,而是会直接使用存储在 ViewState 中的值直接按照上次的方式呈现它们。

    如果您的 jQuery 代码在呈现 HTML 后对其进行了更改,那么服务器将不知道,并且确实没有可行的方法来更改它。这里有趣的问题是:包装跨度和children 属性以及所有这些代码首先是如何应用的?

    您的选择是执行以下操作之一:

    • 发出 AJAX 请求而不是完整的回发,只更改您想要更改的 DOM 部分
    • 在回发后的 DOMReady 上重新应用实现此更改的 jQuery 代码

    编辑

    针对原帖中的修改:

    Category 是你的CheckBoxList 吗?如果您已经迭代地向其中添加了所有列表项,那之后为什么还要重新绑定它呢?我认为第一个 for 循环应该使数据绑定过时。

    我最好的猜测是,当CheckBoxList 被序列化为 ViewState 时,它​​会存储应用于它的属性,以及列表项的 id/value 字典(而不是您迭代应用的其他属性)。

    如果它没有保存在 ViewState 中 - 看起来没有 - 没有真正干净的解决方案可以解决您的问题。解决方法是在每次页面加载时执行代码,或者在子类中继承 CheckBoxList,覆盖 Render 方法,以始终生成您想要的输出。事实上,如果您在整个站点中大量使用此选项,最后一个选项可能非常简洁......?

    【讨论】:

    • 好吧,恐怕我没有一个简单而出色的解决方案,但请看我的编辑
    • 好的,一种变通方法似乎奏效了;我设置了EnableViewState="false",现在它每次都能正确渲染......但在重新加载后删除选定的框:-/
    • 如果它在你禁用视图状态时工作,你必须在每次回发时将它与数据重新绑定。如果您正在将其与每次回发的数据重新绑定,您可以在该绑定中检查您的帖子集合:item.Checked = Request.Form[item.ClientID] == "on";
    • 毫无疑问,这是一个非常聪明的想法,但它对我不起作用......如果我尝试检查Request.Form["Category"],我会收到一个未设置引用的异常:- /
    • 嗯,是的,您的 ID,正如您在 Request.Form 集合中找到的那样,它不是“Category”,而是“ctl00_Menu_Category_0”,因此是 ClientID-part。不过,我不知道这个 ClientID 是在什么时候分配的(但肯定是 将它添加到 Category.Items 之后),所以你可能必须手动生成它 - 'ctl00_Menu_Category'+someIndex - 这有点骇人听闻,但应该可以工作。
    猜你喜欢
    • 2020-07-06
    • 2015-08-15
    • 1970-01-01
    • 1970-01-01
    • 2017-06-18
    • 2020-07-01
    • 2014-07-24
    • 2016-10-26
    • 1970-01-01
    相关资源
    最近更新 更多