0

これは、質問をうまく行うためにコードを単純化するための私の最善の試みです。うまくいけば、それは役に立ちます。

短い:動的に作成されControlたパスがデータベースからロードさRepeaterれ、PlaceHolder. 値は、マスター ページから呼び出される子ページの関数から取得する必要があります。

詳細: 多くの設定を含むマスター ページと、子ページが独自の構成オプションを追加できる領域があります。マスターページが次のようになっているとします。

<%@ Master Language="C#" MasterPageFile="~/MainTemplate.master" CodeBehind="ConfigureChoices.master.cs" Inherits="Demo.ConfigureChoices"
AutoEventWireup="true"  %>


<asp:Content ID="Content1" ContentPlaceHolderID="RenderArea" runat="Server">

    <asp:Panel runat="server" ID="PanelConfiguration">
        <asp:TextBox ID="TextBoxForSomething" runat="Server"/>
        <asp:DropDownList ID="AnotherConfigurableThing" runat="server" OnSelectedIndexChanged="DropDownConfiguration_Click" AutoPostBack="true">
            <asp:ListItem Text="Option 1" Selected="True" Value="1"></asp:ListItem>
            <asp:ListItem Text="Option 2"  Value="2"></asp:ListItem>
            <asp:ListItem Text="Option 3"  Value="3"></asp:ListItem>
        </asp:DropDownList>
        <!--etc-->

        <asp:ContentPlaceHolder ID="CustomSettings" runat="server">
        </asp:ContentPlaceHolder>

        <asp:Button ID="ButtonSubmit" runat="Server" Text="Submit" OnClick="ButtonSubmit_Click" />
    </asp:Panel>

</asp:Content>

コード ビハインドでは、ユーザー ページからのカスタム設定を含め、設定をデータベースに永続化する必要があります。子ページは、データを永続化するために、マスター ページから作成されたデータの一部を必要とします。これを実現するために、子ページの読み込み時にデータが取り込まれ、リダイレクトの前に呼び出されるイベントがあります。次のようになります。

public delegate void BeforeSubmitEventHandler(int configInfoID);
public event BeforeSubmitEventHandler BeforeSubmit;

protected void ButtonSubmit_Click(object sender, EventArgs e)
{
    ConfigInfo config = new ConfigInfo;
    config.EnteredText = TextBoxForSomething.Text;
    config.SelectedValue = AnotherConfigurableThing.SelectedValue;

    int configID = AddToDatabase(config);

    if (BeforeSubmit != null)
        BeforeSubmit(configID);
    Response.Redirect("RedirectURL.aspx");
}

ユーザー ページのカスタム セクションにはRepeater、 、DropDownList、および "追加" がありButtonます。にはRepeater、オプションの名前、簡単な説明、削除イメージ、およびPlaceHolderデータベースからカスタム コントロールをロードするための があります。コードの後の詳細:

<%@ Page Title="" Language="C#" MasterPageFile="~/ConfigureChoices.master" ValidateRequest="false"
    AutoEventWireup="true" Inherits="Demo.CustomChoicePage1" Codebehind="CustomChoicePage1.aspx.cs" 
    MaintainScrollPositionOnPostback="true" %>

<asp:Content ID="MyContent" ContentPlaceHolderID="CustomSettings" runat="server">
    <asp:Repeater ID="RepeaterSelectedOptions" OnItemCreated="OnOptionAdded" runat="server">
        <HeaderTemplate>
            <table id="SelectedOptionsTable">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Description</th>
                        <th>Remove</th>
                    </tr>
                </thead>

                <tbody>
        </HeaderTemplate>

        <ItemTemplate>
                    <tr>
                        <td>
                            <%# Server.HtmlEncode(Eval("Name").ToString()) %>
                        </td>
                        <td>
                            <%# Server.HtmlEncode(Eval("Description").ToString()) %>
                        </td>
                        <td>
                            <asp:ImageButton ImageUrl="delete.png" ID="ImgDeleteOption" runat="server" OnCommand="DeleteOption_Click" 
                                CommandArgument='<%# Eval("OptionID") %>' />
                        </td>
                    </tr>
                    <asp:PlaceHolder runat="server" ID="optionConfiguration" />
        </ItemTemplate>

        <FooterTemplate>
                </tbody>
            </table>
        </FooterTemplate>
    </asp:Repeater>

    <br />

    <asp:DropDownList ID="DropDownListAvailableOptions" runat="server" />
    <asp:Button ID="ButtonAddOption" runat="server" Text="Add Option" OnCommand="AddOption_Click" />

</asp:Content>

コード ビハインドでは、次のコードを使用しRepeaterて初めてデータが取り込まれPage_Loadます (C# と疑似コードを組み合わせて、このすでに長い質問を短くしています)。

protected void Page_Load(object sender, EventArgs e)
{
    ((ConfigureChoices)Master).BeforeSubmit += OnSubmit;
    if (!Page.IsPostBack)
    {
        RefreshOptions();
    }
}

protected void RefreshOptions()
{
    List<Option> fullList = GetOptionsFromDB();
    List<Option> availableList = new List<Option>();
    List<Option> selectedList = new List<Option>();
    List<int> selectedOptions = GetSelectedOptions();

    // Logic here to set the available/selected Lists

    DropDownListAvailableOptions.DataSource = availableList;
    DropDownListAvailableOptions.DataBind();

    RepeaterSelectedOptions.DataSource = selectedList;
    RepeaterSelectedOptions.DataBind();
}

public List<short> GetSelectedOptions()
{
    List<int> selectedOptions = this.ViewState["SelectedOptions"];
    if (selectedOptions == null)
    {
        selectedOptions = new List<int>();
        foreach (Option option in GetOptionsFromDB())
        {
            selectedOptions.Add(option.OptionID);
        }
    }
    return selectedOptions;
}

追加または削除ボタンをクリックすると、次のメソッドが使用されます。

public void AddOption_Click(object sender, CommandEventArgs e)
{
    List<int> selectedOptions = GetSelectedOptions();

    selectedOptions.Add(Convert.ToInt32(DropDownListAvailableOptions.SelectedValue));
    this.ViewState["SelectedOptions"] = selectedTests;

    RefreshOptions();
}

public void DeleteOption_Click(object sender, CommandEventArgs e)
{
    List<int> selectedOptions = GetSelectedOptions();

    selectedOptions.Remove(Convert.ToInt32(e.CommandArgument));
    this.ViewState["SelectedOptions"] = selectedOptions;

    RefreshOptions();
}

最後に、問題があると思われる場所の要点と、私が試したことの説明です。オプションがコントロールに追加されると、プレースホルダーにロードする必要がある追加の ascx があるかどうかを確認するために、別のテーブルが照会されます。これは、 で指定されたメソッドで発生し OnItemCreatedますRepeater

protected void OnOptionAdded(Object sender, RepeaterItemEventArgs e)
{
    if (e.Item == null || e.Item.DataItem == null)
        return;

    short optionID = ((Option)e.Item.DataItem).OptionID;
    OptionControl optionControl = GetControlForOptionFromDB(optionID);

    if (optionControl == null)
        return;

    CustomOptionControl control = (CustomOptionControl)this.LoadControl(optionControl.Path);
    control.ID = "CustomControl" + optionID.ToString();

    TableRow tableRow = new TableRow();
    tableRow.ID = "CustomControlTR" + optionID.ToString();
    tableRow.CssClass = "TestConfiguration";

    TableCell tableCell = new TableCell();
    tableCell.ID = "CustomControlTC" + optionID.ToString();
    tableCell.ColumnSpan = 3;

    e.Item.FindControl("optionConfiguration").Controls.Add(tableRow);
    tableRow.Cells.Add(tableCell);
    tableCell.Controls.Add(control);
}

したがって、ページ上にコントロールが表示され、リストが正しく機能するなど、上記のすべてが「機能」します。[送信] ボタンをクリックすると、リクエスト フォーム変数に構成が表示されます (この例では、単一のチェックボックスとします)。ただし、子ページのコールバック メソッドにブレークポイントを設定するCustomOptionControlと、RepeaterSelectedOptions. のみOptionが存在します。

私は少なくとも次のことを試しました(しかし、私が試したすべてのステップを正直に思い出すことはできません):

  • ベースをロードする呼び出しの後にRefreshOptionsオーバーライドへの呼び出しを追加するLoadViewState
  • 代わりに私の初期Repeaterバインディングを行うPage_InitPage_Load
  • 表の行、セル、およびカスタム コントロールを相互に、およびメイン ページに追加するさまざまな順序

次のコードのコメント行のようなものを機能させるには、このページとそれに必要なデータバインディング イベントをどのように構成すればよいでしょうか? メソッドの先頭でブレークして を調べるとRepeaterOptions.ControlsCustomOptionControls がなくなっています。

protected void OnSubmit(int configID)
{
    //List<CustomOptionControl> optionsToInsert = find CustomOptionControls in RepeaterOptions (probably an iterative search through the Controls);
    //foreach (CustomOptionControl control in optionsToInsert)
    //{
    //    control.AddOptionToDatabase(configID);
    //}
}
4

1 に答える 1

0

何が変わったのかはわかりません。おそらく、上記のすべてを使用してラバーダックのデバッグに休憩を取っていたのでしょう。私は戻って、以前に持っていたもののいくつか(挿入の順序、使用する呼び出しなど)を微調整して、それらが違いを生むかどうかを確認しましたが、いずれにせよ、上記で適切Controlに永続化されていますViewStateコード。以下が追加されている限り、マスターページ呼び出しからのポストバックで利用できます (私が以前に試したことの箇条書き 1):

    protected override void LoadViewState(object savedState)
    {
        base.LoadViewState(savedState);
        RefreshOptions();
    }

以前は、選択したオプションを維持するために追加されたものsavedStateのみを表示していました。List<int>微調整とデバッグのある時点で、作成したコントロールがビューステートになり、RefreshOptions呼び出しを追加できることがわかりました。これは、追加/削除のポストバックで への 2 つの呼び出しがあることを意味しますがRefreshOptions、動作は依然として正しいため、それを回避するか無視することができます。ご覧いただきありがとうございます。

于 2013-07-03T16:38:52.933 に答える