これは、質問をうまく行うためにコードを単純化するための私の最善の試みです。うまくいけば、それは役に立ちます。
短い:動的に作成され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_Init
Page_Load
- 表の行、セル、およびカスタム コントロールを相互に、およびメイン ページに追加するさまざまな順序
次のコードのコメント行のようなものを機能させるには、このページとそれに必要なデータバインディング イベントをどのように構成すればよいでしょうか? メソッドの先頭でブレークして を調べるとRepeaterOptions.Controls
、CustomOptionControl
s がなくなっています。
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);
//}
}