5

私には2つの方法があります。最初に1つのテーブルを動的に作成し、そのテーブルをPlaceHolderに追加します。

private void generateData(){
    Table tbl = new Table();
    tbl.ID = "table1";
    holder_info.Controls.Add(tbl);
    // ...adding tr's and td's....
    // ...adding CheckBox in tds....
}

このメソッド内で.FindControl( "...")を実行すると、次を使用してコントロールを見つけることができます。

CheckBox check = (CheckBox)holder_info.FindControl("checkbox1");

大丈夫ですが、私がふりをすることはできません。

2番目の方法では、ユーザーがcheckBoxをチェックして何かをしたかどうかを確認したいのですが、コントロールが見つかりません(常にnullを返します)。

protected void saveInfo_Click(object sender, ImageClickEventArgs e)
{
  CheckBox check = (CheckBox)holder_info.FindControl("checkbox1");
  if(check.checked){ ... }
}

また、コントロール「table1」を見つけようとすると、nullになります。

なぜこれが起こるのですか?

4

3 に答える 3

5

これは、コントロールをページに動的に追加しているためです。ボタンページをクリックすると、ポストバックが取得され、動的に追加されたコントロールが削除されます。そのため、ボタンクリックイベントでチェックボックスコントロールを見つけることができません。

動的コントロールについては、記事「ASP.NETアプリケーションで動的に作成されたコントロールの状態を保持する(コードプロジェクト)」を確認してください。

于 2012-08-22T15:57:53.083 に答える
3

FindControl()直接の子のみを検出し、それらの子の子は検出しません。

やりたいことを行うには、子コントロールを再帰的に見つけるルーチンを作成する必要があります。

于 2012-08-22T15:58:53.777 に答える
1

Pranayが説明したように、これはコントロールを動的に追加しているためです。ポストバック前と同じようにページを再構築する必要があります。さらに、テーブルコントロールは、以前に表示された情報を記憶する場合、優れたWebコントロールではありません。リピーター、DataList、またはDataGridを使用すると運が良くなる可能性があります。比較は、DataGrid、DataList、またはRepeater(MSDN)をいつ使用するかを決定する際に利用できます。

実例を示すために、リピーターを実装する方法の簡単な例を示すことができます。これは、コントロールIMOの単純なものです。したがって、ポストバック(ボタンクリックなど)にテーブルを追加する代わりに、マークアップにリピーターを追加し、データを表示するときに表示するように設定します。このように、動的制御について気にする必要はありません。必要なときにそこにあります。

したがって、チェックボックスが付いたリピーターの基本的なマークアップは次のとおりです。

<asp:Repeater ID="myTable" runat="server">
    <HeaderTemplate>
        <table cellpadding="4" cellspacing="0">
        <thead>
            <tr>
                <th></th>
                <th>Name</th>
                <th>Company</th>
            </tr>
        </thead>
        <tbody>
    </HeaderTemplate>
    <ItemTemplate>
    <tr>
        <td>
            <asp:HiddenField ID="uidfield" Value='<%# Eval("Uid") %>' runat="server" />
            <asp:CheckBox ID="valuefield" Checked='<%# Eval("IsChecked") %>' runat="server" />
        </td>
        <td>
            <asp:Label Text='<%# Eval("Name") %>' runat="server" />
        </td>
        <td>
            <asp:Label Text='<%# Eval("Company") %>' runat="server" />
        </td>
    </tr>
    </ItemTemplate>
    <FooterTemplate>
    </tbody> </table>
    </FooterTemplate>
</asp:Repeater>

ご覧のとおり、テーブルは手動で作成されます(必要がない場合は、代わりにDataGridを使用できます)。これで、次のようなモデルであるクラスを作成できます。

public class Person {
  public Person() { }

  public Person(Guid id, string name, string company) {
    this.Uid = id;
    this.Name = name;
    this.Company = company;
  }

  public Guid Uid { get; set; }

  public string Name { get; set; }

  public string Company { get; set; }
}

そして、(Webページコントロールのように)ビューの「ニーズに対応する」viewmodelクラス。追加のプロパティIsCheckedに注意してください。これは、モデルの一部であってはなりません(人はどのようにチェックされますか?)が、viewmodelクラスにはうまく適合します。

public class PersonViewModel {
  private Person model;
  public PersonViewModel(Person model) {
      this.model = model;
  }

  public Guid Uid { get { return model.Uid; } }

  public string Name { get { return model.Name; } }

  public string Company { get { return model.Company; } }

  public bool IsChecked { get; set; }
}

さて、コードビハインドについても同様です。リピーターコントロールを使用する場合は、リストにバインドする必要があります。IEnumerableから継承するもののインスタンスは問題ないので、それを接続する必要があります。

ページのコードビハインドに、これらのメソッドを追加します。

protected override void OnInit(EventArgs e) {
    base.OnInit(e);
    mailinglists.DataBinding += bindMyTable;
}

protected override void OnLoad(EventArgs e) {
    base.OnLoad(e);
    if (!Page.IsPostBack) {
        DataBind();
    }
}

private void bindMyTable(object sender, EventArgs e) {
    // Are the conditions set for adding data to the table?
    if (conditionsMet()) {
        myTable.DataSource = getDataSource();
    }
}

private IEnumerable<PersonViewModel> getDataSource() {
     List<PersonViewModel> view = new List<PersonViewModel>();
     view.Add(new PersonViewModel(new Person() { Uid = Guid.NewGuid(), Name = "Example", Company = "Co" }));
     return view;
}

myTable.DataBind()これで、条件が満たされたとき、たとえばボタンをクリックしたときに電話をかけるだけです。ボタンをクリックして、どのチェックボックスがオンになっているかを確認する必要がある場合は、次のrepeater.Itemsように、プロパティを使用してそれらを繰り返すことができます。

private void onValidatePage() {
    List<Guid> checks = new List<Guid>();
    foreach (RepeaterItem repeatitem in myTable.Items) {
        string uid = ((HiddenField)repeatitem.FindControl("uidfield")).Value;
        bool value = ((CheckBox)repeatitem.FindControl("valuefield")).Checked;
        if (value) {
            checks.Add(new Guid(uid));
        }
    }
    // Now "checks" hold all the id's of the checked items
}
于 2012-08-22T16:59:42.487 に答える