Gần đây tôi đã phải quay lại để xử lý mã webform và đã gặp sự cố khi cố cập nhật trang hiện tại hiển thị danh sách các câu trả lời khảo sát.Làm thế nào để bạn nhận được các giá trị từ các điều khiển động trong một ListView trên postback?
Tôi có một ListView hiển thị chi tiết về những người đã trả lời bản khảo sát. Khi bạn nhấp vào biểu tượng trong hàng có hàng nhập chế độ chỉnh sửa và hiển thị thông tin của họ (tên, email, v.v ...) làm hộp nhập.
Cho đến giờ rất tốt, bây giờ tôi cần thêm câu hỏi và câu trả lời cho cuộc khảo sát đó và người đó. Viết chúng ra dễ dàng, nhưng khi postback xảy ra hàng sẽ trở lại ItemTemplate và các điều khiển đã biến mất.
Tôi biết với các điều khiển động mà bạn phải tạo trong Page_Init để các biểu mẫu web có thể rebind chúng, nhưng ở đây các điều khiển không được tạo cho đến khi sự kiện ItemItem ItemEditing và dữ liệu được lưu trong sự kiện ItemUpdating.
Tôi bị mắc kẹt về cách tôi có thể thực hiện các điều khiển ở đúng nơi với đúng dữ liệu vào đúng điểm trong vòng đời. Ngay bây giờ tôi đang cố gắng để kéo các giá trị từ Request.Form nhưng với một CheckboxList thật khó để tìm ra những gì đã được chọn.
Edit: ví dụ mới mà thực sự nên chạy
<%@ 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>
Sau đó, các mã sau:
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, tôi đã thêm một ví dụ. những gì tôi có nghĩa là bằng cách trở lại ItemTemplate nên hy vọng là một chút rõ ràng hơn, câu hỏi chỉ được hiển thị trong EditItemTemplate bạn điền chúng vào, lưu của mình và sau đó trang hiển thị ItemTemplate mà không có những điều khiển. – Mant101
Tôi đã thử điều này, nhưng họ không có các giá trị được đăng lại trong đó. Từ những gì tôi đã có thể tìm thấy tôi cần phải tạo chúng trong Page_Load cho dữ liệu để rebind, và làm cho chúng trong iL_ItemUpdating là quá muộn trong vòng đời. – Mant101
@ Mant101 - Page_Load sẽ là một nơi tốt hơn để tạo chúng. Có thể bạn có thể kiểm tra 'IsPostBack && (EditIndex> = 0)' trong Page_Load và tạo lại các điều khiển ở đó. Nếu bạn có thể cung cấp một mẫu hoàn chỉnh tối thiểu để chứng minh sự cố (http://stackoverflow.com/help/mcve) Tôi hoặc người khác sẽ có thể trợ giúp. – Joe