我正在尝试设置一个如下所示的表格:
| 姓名 | 电子邮件 | CurrentUserGroup | ChangeUserGroup |
每行的ChangeUserGroup列都有一个DropDownList控件,其中包含3个选项(student,advisor,admin),在SelectedIndexChanged事件中,每行都更新它的用户的userGroup。
几个星期前我有这个工作,但从来没有做过改变,我丢失了它们,不记得我是如何工作的。
这就是我目前按表格构建的方式:
Page_Load调用BuildUserTableHtml(),在表中创建DropDownList。
private void buildUserTableHtml(List<User> users)
{
StringWriter htmlString = new StringWriter();
using (HtmlTextWriter writer = new HtmlTextWriter(htmlString))
{
foreach(User user in users)
{
string name = user.firstName + " " + user.lastName;
//tr
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
//td 1
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write(name);
writer.RenderEndTag(); //td 1 end
//td 2
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write(user.email);
writer.RenderEndTag(); //td 2 end
//td 3
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write(user.userGroup);
writer.RenderEndTag(); //td 3 end
//td
HtmlTableCell cell = new HtmlTableCell();
DropDownList ddl = new DropDownList();
ddl.Items.Add(new ListItem("UerGroup", "0"));
ddl.Items.Add(new ListItem("User", "USER"));
ddl.Items.Add(new ListItem("Advisor", "ADVISOR"));
ddl.Items.Add(new ListItem("Admin", "ADMIN"));
ddl.SelectedIndex = 0;
ddl.AutoPostBack = true;
ddl.SelectedIndexChanged += userGroup_ItemChanged;
cell.Controls.Add(ddl);
cell.RenderControl(writer); // end td 4
//td 5
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.AddAttribute(HtmlTextWriterAttribute.Class, "glyphicon glyphicon-remove");
writer.AddAttribute("data-toggle", "tooltop");
writer.AddAttribute(HtmlTextWriterAttribute.Title, "Delte User");
writer.AddAttribute("href", "#");
writer.RenderBeginTag(HtmlTextWriterTag.A);
writer.RenderBeginTag(HtmlTextWriterTag.Span);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag(); //td 5 end
writer.RenderEndTag(); //tr end
}
}
userTable_PlcHldr.Controls.Add(new Literal { Text = htmlString.ToString() });
}
userTable_PlcHldr是已构造的表中的.NET占位符,该表使用javascript插件进行搜索。
<table id="userTable" class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>User Group</th>
<th>Change</th>
<th>Delete User</th>
</tr>
</thead>
<tbody>
<asp:PlaceHolder ID="userTable_PlcHldr" runat="server" ></asp:PlaceHolder>
</tbody>
</table>
更改DropDownList的选定值 - 应该触发userGroup_ItemChanged()
protected void userGroup_ItemChanged(object sender, EventArgs e)
{
UserGroup userGroup;
DropDownList ddl = (DropDownList)sender;
bool update = true;
string value = ddl.SelectedValue;
int ID = Int32.Parse(ddl.ID.Substring(1));
switch (value)
{
case "ADMIN":
userGroup = UserGroup.ADMIN;
break;
case "ADVISOR":
userGroup = UserGroup.ADVISOR;
break;
case "USER":
userGroup = UserGroup.USER;
break;
default:
userGroup = UserGroup.DEFUALT;
update = false;
break;
}
try
{
if (update)
UserGroups.UpdateUserGroup(ID, userGroup);
} catch (Exception ex)
{
string error = ex.Message;
}
}
但是,此代码无效。它正确呈现页面上的控件,但SelectedItemChanged永远不会触发。 AutoPostBack已启用。我认为这是因为控件实际上并没有正确地添加到页面中,而服务器也看不到它们。
任何人都知道如何做到这一点?
答案 0 :(得分:0)
我能够使用asp:Repeater来实现这一点。
<table id="userTable" class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>User Group</th>
<th>Change</th>
<th>Delete User</th>
</tr>
</thead>
<tbody>
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<tr>
<td><asp:Label runat="server" Text='<%# Eval("firstName").ToString() + " " + Eval("lastName").ToString() %>'></asp:Label></td>
<td><asp:Label runat="server" Text='<%# Eval("email") %>'></asp:Label></td>
<td><asp:Label runat="server" Text='<%# Eval("userGroup") %>'></asp:Label></td>
<td>
<asp:DropDownList AutoPostBack="true" OnSelectedIndexChanged="userGroup_ItemChanged" runat="server" CssClass="form-control">
<asp:ListItem Value="0"> <-UserGroup-> </asp:ListItem>
<asp:ListItem Value="USER"> User </asp:ListItem>
<asp:ListItem Value="ADVISOR"> Advisor </asp:ListItem>
<asp:ListItem Value="ADMIN"> Admin </asp:ListItem>
</asp:DropDownList>
</td>
<td>
<asp:LinkButton ID="deleteUser" runat="server" CssClass="btn btn-secondary" OnClick="deleteUser_Click">
<span class ="glyphicon glyphicon-remove" data-toggle="tooltip" title="Delete User"></span>
</asp:LinkButton>
</td>
<asp:HiddenField ID="hiddenID" runat="server" Value='<%# Eval("userID") %>' />
</tr>
</ItemTemplate>
</asp:Repeater>
</tbody>
</table>
然后在我的OnSelectedIndexChanged方法userGroup_ItemChanged()中,我通过执行以下操作获得了hiddenID:
DropDownList ddl = (DropDownList)sender;
RepeaterItem item = (RepeaterItem)ddl.NamingContainer;
HiddenField hiddenID = (HiddenField)item.FindControl("hiddenID");
int ID = int.Parse(hiddenID.Value);
答案 1 :(得分:-1)
Web窗体的方式不是构建字符串并将其附加到控件层次结构中。那太乱了。
相反,Web窗体将鼓励您将数据绑定到页面上已存在的控件,该控件已在aspx中声明。
我准备了一个可以放入新的Web窗体应用程序的工作演示,它应该正常工作:
标记:
<%@ Page Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebFormsHelloWorld._Default" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<asp:Repeater runat="server" ID="UsersRepeater" ItemType="WebFormsHelloWorld.User">
<HeaderTemplate>
<table>
<tr>
<th>Name</th>
<th>Email</th>
<th>Group</th>
<th>Change Group</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%#: Item.Name %></td>
<td><%#: Item.Email %></td>
<td><%#: Item.Group %></td>
<td>
<asp:HiddenField runat="server" ID="UsersNameHiddenField" Value="<%#: Item.Name %>" />
<asp:DropDownList runat="server" OnSelectedIndexChanged="Unnamed_SelectedIndexChanged" AutoPostBack="true">
<asp:ListItem Text="--Select Item--" Value="SelectItem" />
<asp:ListItem Text="Admin" Value="Admin" />
<asp:ListItem Text="Advisor" Value="Advisor" />
<asp:ListItem Text="User" Value="User" />
</asp:DropDownList>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
</asp:Content>
正如您所看到的,我们已经在ASPX页面中很好地声明了我们的标记。我们正在利用的另一个很酷的东西是强类型模型。通过设置转发器的ItemType,我们可以使用Item.Property
来访问模型对象的属性。
代码背后:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebFormsHelloWorld
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
var users = new List<User>
{
new User { Name = "Luke Skywalker", Email="luke@skywalker.com", Group = "Admin"},
new User { Name = "Han Solo", Email="han@solo.com", Group = "Advisor"},
new User { Name = "Leia Organa", Email="lea@alderan.com", Group = "User"},
};
UsersRepeater.DataSource = users;
UsersRepeater.DataBind();
}
}
protected void Unnamed_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList changedDropDownList = sender as DropDownList;
var parentRow = changedDropDownList.Parent;
var hiddenField = parentRow.FindControl("UsersNameHiddenField") as HiddenField;
var userName = hiddenField.Value;
Debug.WriteLine($"User {userName}, new group {changedDropDownList.SelectedValue}");
}
}
public class User
{
public string Name { get; set; }
public string Email { get; set; }
public string Group { get; set; }
}
}
出于测试目的,我在代码中创建了一个用户列表。可能你的真实应用程序,你会从某个存储库中获取那些。然后,当它不是回发时,我们将它们绑定到转发器。
在下拉列表的事件处理程序中,我们从隐藏字段获取我们正在修改的用户的名称。我们不得不做一些愚蠢的控制层次遍历来获取数据,这是Web Forms的烦人部分。我们将发送者(启动事件的控件)转换为下拉列表并获取其当前选定的值。最后,我们将其写入调试控制台。在您的应用程序中,您可能希望更新存储库中的域对象。