0

私は動的に値を割り当てる自分のページで<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と、すべてSubCatの もチェックされます。

jQuery コードは、 -attribute<span>と等しいクラスを持つすべての を検索するため、jQuery が機能するこの構造を維持する必要があります。children

しかし、ページをリロードしたり、リンクをたどったりすると、リストは突然次のようになります。

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

1 に答える 1

0

ページをリロードするたびに、HTML コード全体が常にレンダリングされます。チェックすることで防止できるのは、今回の HTML のレンダリング方法IsPostBack変更することです。つまり、ページがポストバックされると、サーバーはチェックボックス リストを新しい値にバインドせず、ViewState に保存されている値を使用して、前回とまったく同じ方法でそれらを直接レンダリングします。

HTML がレンダリングされた後に jQuery コードが HTML を変更した場合、サーバーはそれを認識できず、それを変更する実行可能な方法は実際にはありません。ここで興味深い質問は、ラッピング スパンとchildrenプロパティ、およびすべてのコードが最初にどのように適用されるのかということです。

オプションは、次のいずれかを実行することです。

  • 変更したい DOM の部分のみを変更して、完全なポストバックではなく AJAX リクエストを作成します。
  • ポストバック後の DOMReady 時に、この変更を実現する jQuery コードを再適用します。

編集

元の投稿の編集に応じて:

CategoryあなたのですかCheckBoxList?すべてのリスト アイテムを繰り返し追加した場合、その後、再度データ バインドするのはなぜでしょうか。最初の for ループは、データバインディングを時代遅れにするべきだと思います。

ここでの私の最善の推測は、CheckBoxListViewState にシリアル化されているときに、それに適用されたプロパティを、リスト項目の id/value ディクショナリと共に保存することです (繰り返し適用する追加のプロパティではありません)。

ViewState に保存されていない場合 (保存されていないように見える場合)、問題に対する明確な解決策はありません。回避策は、すべてのページロードでコードを実行するか、メソッドCheckBoxListをオーバーライドするサブクラスで を継承してRender、常に必要な出力を生成することです。実際、サイト全体でこれを頻繁に使用している場合、最後のオプションは非常に優れている可能性があります...?

于 2009-12-10T10:54:17.277 に答える