Niedawno musiałem wrócić do rozwiązywania problemów z kodem formularzy internetowych i napotkałem problem próbujący zaktualizować istniejącą stronę z listą odpowiedzi ankietowych.W jaki sposób otrzymujesz wartości z dynamicznych elementów sterujących w widoku listy na poczcie zwrotnej?
Mam ListView pokazujące szczegóły osób, które odpowiedziały na ankietę. Po kliknięciu ikony w wierszu ten wiersz wchodzi w tryb edycji i pokazuje jego informacje (imię, adres e-mail itp.) Jako pola wprowadzania.
Na razie dobrze, teraz muszę dodać pytania i odpowiedzi do tej ankiety i tej osoby. Pisanie ich jest łatwe, ale gdy oddzwoni się, wiersz wraca do ItemTemplate, a kontrola nie działa.
wiem z dynamicznymi kontroli Miałeś aby stworzyć w Page_Init tak webforms można je ponownie powiązać, ale tutaj kontrole nie są stworzone do imprezy ListItem ItemEditing, a dane zapisane w razie ItemUpdating.
Utknąłem na tym, jak mogę sterować we właściwym miejscu z odpowiednimi danymi we właściwym punkcie cyklu życia. Teraz próbuję pobrać wartości z Request.Form, ale z CheckboxList trudno jest ustalić, co zostało wybrane.
Edit: New przykład, że należy właściwie prowadzony
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="QuestionExample.aspx.cs" Inherits="QuestionExample" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<table>
<asp:ListView runat="server" ID="LV" OnItemEditing="LV_OnItemEditing" OnItemUpdating="LV_OnItemUpdating">
<LayoutTemplate>
<tr>
<td><asp:PlaceHolder runat="server" ID="itemPlaceHolder"></asp:PlaceHolder></td>
</tr>
</LayoutTemplate>
<ItemTemplate>
<asp:LinkButton ID="EditButton" runat="server" CommandName="Edit" Text="Edit"/>
ID: <asp:Label runat="server" ID="lblLeadID" Text="<%# ((Lead)Container.DataItem).LeadID %>" /> Name: <%# ((Lead)Container.DataItem).Name %><br/>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID="UpdateButton" runat="server" CommandName="Update" Text="Update" />
ID: <asp:Label runat="server" ID="lblLeadID" Text="<%# ((Lead)Container.DataItem).LeadID %>" /> <asp:Label runat="server">Name</asp:Label>
<asp:TextBox runat="server" id="tbName" Text="<%# ((Lead)Container.DataItem).Name %>"></asp:TextBox>
<asp:Panel runat="server" id="pnlQuestions"></asp:Panel>
</EditItemTemplate>
</asp:ListView>
</table>
</form>
</body>
</html>
Następnie kod tyle:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class QuestionExample : Page
{
#region fake data
protected List<Question> Questions = new List<Question>()
{
new Question { QuestionID = 0, QuestionType = QuestionType.Textbox, QuestionText = "TextBox", Options = null },
new Question { QuestionID = 1, QuestionType = QuestionType.DropDownList, QuestionText = "DDL", Options = new List<string> { "A", "B", "C"} },
};
protected List<Lead> Leads = new List<Lead>
{
new Lead { LeadID = 0, Name = "Bob", Answers = new Dictionary<string, string> { { "TextBox", "Hi" }, { "DDL", "B" } } },
new Lead { LeadID = 1, Name = "Fred", Answers = new Dictionary<string, string> { { "TextBox", "Stuff" }, { "DDL", "C" } } },
};
#endregion
protected void Page_Load(object sender, EventArgs e)
{
LV.DataSource = Leads;
LV.DataBind();
}
protected void LV_OnItemEditing(object sender, ListViewEditEventArgs e)
{
LV.EditIndex = e.NewEditIndex;
LV.DataBind();
var leadLabel = (Label)LV.Items[e.NewEditIndex].FindControl("lblLeadID");
var leadID = int.Parse(leadLabel.Text);
var panel = (Panel)LV.Items[e.NewEditIndex].FindControl("pnlQuestions");
var lead = Leads.First(l => l.LeadID == leadID);
foreach (var answer in lead.Answers)
{
var question = Questions.First(q => q.QuestionText == answer.Key);
panel.Controls.Add(CreatQuestionControl(question, lead, true));
}
}
protected Control CreatQuestionControl(Question question, Lead lead, bool setAnswers)
{
Control result = null;
switch (question.QuestionType)
{
case QuestionType.Textbox:
var tb = new TextBox();
if (setAnswers)
{
var answer = lead.Answers[question.QuestionText];
tb.Text = answer;
}
result = tb;
break;
case QuestionType.DropDownList:
var ddl = new DropDownList { DataSource = question.Options };
ddl.DataBind();
if (setAnswers)
{
var answer = lead.Answers[question.QuestionText];
ddl.SelectedValue = answer;
}
result = ddl;
break;
}
return result;
}
protected void LV_OnItemUpdating(object sender, ListViewUpdateEventArgs e)
{
// Get input data here somehow
LV.EditIndex = -1;
}
}
public class Lead
{
public int LeadID { get; set; }
public string Name { get; set; }
public Dictionary<string, string> Answers { get; set; }
}
public class Question
{
public int QuestionID { get; set; }
public string QuestionText { get; set; }
public QuestionType QuestionType { get; set; }
public List<string> Options { get; set; }
}
public enum QuestionType
{
Textbox = 0,
DropDownList = 1,
}
OK, dodałem przykład. co mam na myśli, powracam do ItemTemplate powinno być nieco bardziej przejrzyste, pytania są wyświetlane tylko w EditItemTemplate, w którym je wypełniasz, jego zapisanie, a następnie strona pokazuje ItemTemplate bez tych kontrolek. – Mant101
Próbowałem już tego, ale nie mają wartości w nich umieszczone. Z tego, co udało mi się znaleźć, muszę je utworzyć w Page_Load, aby dane mogły zostać ponownie powiązane, a uczynienie ich w iL_ItemUpdating jest zbyt późne w cyklu życia. – Mant101
@ Mant101 - Page_Load byłoby lepszym miejscem do ich tworzenia. Być może mógłbyś sprawdzić 'IsPostBack && (EditIndex> = 0)' w Page_Load i odtworzyć tam kontrolki. Jeśli możesz podać minimalną kompletną próbkę, która demonstruje problem (http://stackoverflow.com/help/mcve) ja lub ktoś inny będzie w stanie Ci pomóc. – Joe