C# 从母版页上注册的回调中检索ascx控件值。添加到中继器的控件';创建过程中的s占位符

C# 从母版页上注册的回调中检索ascx控件值。添加到中继器的控件';创建过程中的s占位符,c#,asp.net,postback,dynamic-controls,C#,Asp.net,Postback,Dynamic Controls,这是我简化代码的最佳尝试,可以很好地提问。希望能有帮助 简而言之:我需要获取动态创建的控件的值,该控件的路径从数据库加载并添加到包含占位符的中继器中。需要从母版页调用的子页上的函数中检索该值 长报告: 我有一个母版页,上面有很多设置,还有一个子页可以添加自己配置选项的区域。假设母版页如下所示: <%@ Master Language="C#" MasterPageFile="~/MainTemplate.master" CodeBehind="ConfigureChoices.master

这是我简化代码的最佳尝试,可以很好地提问。希望能有帮助

简而言之:我需要获取动态创建的
控件的值,该控件的路径从数据库加载并添加到包含
占位符的
中继器中。需要从母版页调用的子页上的函数中检索该值

长报告: 我有一个母版页,上面有很多设置,还有一个子页可以添加自己配置选项的区域。假设母版页如下所示:

<%@ 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>
用户页面的自定义部分有一个
中继器
、一个
下拉列表
、和一个“添加”
按钮
Repeater
具有选项名称、简短描述、删除图像和用于从数据库加载自定义控件的
占位符。在代码之后介绍更多内容:

<%@ 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>
如果单击“添加”或“删除”按钮,将使用以下方法:

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();
}
所以上面所有的“工作”都是因为我看到了页面上的控件,列表工作正常,诸如此类。当我单击“Submit”按钮时,我会看到RequestForm变量中的配置(为了本例的缘故,让我们假设它是一个复选框)。但是,在子页面上的“我的回调方法”中设置断点时,
自定义选项控件
似乎不在
中继器选择选项
中。只有
选项
存在

我至少试过以下几步,甚至更多(但老实说,我记不起我试过的每一步):

  • 将对刷新选项的调用添加到覆盖的加载视图状态 在调用加载基础之后
  • 做我的初始
    中继器
    绑定 在
    Page\u Init
    中,而不是
    Page\u Load
  • 将表行、单元格和自定义控件添加到彼此和主控件的不同顺序 页面
我应该如何构造这个页面及其必要的数据绑定事件,以便我可以使下面代码中的注释行工作?当我在方法的开头中断并查看
RepeaterOptions.Controls
时,
自定义选项control
将消失

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);
    //}
}
submit上受保护的void(int-configID)
{
//List optionsToInsert=在RepeaterOptions中查找CustomOptionControls(可能是通过控件的迭代搜索);
//foreach(选项ToInsert中的CustomOptionControl控件)
//{
//control.AddOptionToDatabase(配置ID);
//}
}

我不确定发生了什么变化,可能是因为使用了上述所有功能,才暂时停止了橡皮鸭调试。我回到过去,试着调整一些我以前做过的事情(插入顺序、调用使用顺序等),看看它们是否有区别,但不管怎样,
控件现在都被保存在
ViewState
中,并正确地使用上述代码。只要添加以下内容(我以前尝试过的项目符号1),就可以从母版页调用回发:

早些时候,
savedState
仅显示添加到其中以维护所选选项的
列表。在调整和调试过程中的某个时刻,我看到我创建的控件现在处于viewstate状态,并且添加了一个
RefreshOptions
调用。这意味着在回发add/remove时有两个调用
RefreshOptions
,但我可以解决这个问题,也可以忽略它,因为行为仍然正确。谢谢你的关注

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();
}
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);
}
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);
    //}
}
    protected override void LoadViewState(object savedState)
    {
        base.LoadViewState(savedState);
        RefreshOptions();
    }