C# 将带有事件的DropDownList动态添加到HTML表中

C# 将带有事件的DropDownList动态添加到HTML表中,c#,asp.net,drop-down-menu,C#,Asp.net,Drop Down Menu,我正在尝试设置一个如下所示的表: |名称|电子邮件|当前用户组|更改用户组| 其中,每行的ChangeUserGroup列都有一个DropDownList控件,该控件具有3个选项(学生、顾问、管理员),在SelectedIndexChanged事件中,每行更新其用户的用户组 几周前,我已经开始工作了,但从未提交过更改,我丢失了它们,也记不起我是如何工作的 这就是我目前按表构建的方式: Page_Load调用BuildUserTableHtml(),该函数在表中创建DropDownList pri

我正在尝试设置一个如下所示的表:

|名称|电子邮件|当前用户组|更改用户组|

其中,每行的ChangeUserGroup列都有一个DropDownList控件,该控件具有3个选项(学生、顾问、管理员),在SelectedIndexChanged事件中,每行更新其用户的用户组

几周前,我已经开始工作了,但从未提交过更改,我丢失了它们,也记不起我是如何工作的

这就是我目前按表构建的方式:

  • 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() });
    }
    
  • 但是,此代码不起作用。它正确地呈现页面上的控件,但SelectedItemChanged从不激发。已启用自动回发。我认为这是因为控件实际上没有正确地添加到页面中,而服务器没有看到它们


    有人知道怎么做吗

    我能够使用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>
    

    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>
    
    出于测试目的,我在代码中创建了一个用户列表。对于您的真实应用程序,您可能会从某个存储库中获取这些信息。然后,当中继器不是回发时,我们将它们绑定到中继器


    在dropdownlist的事件处理程序中,我们从一个隐藏字段中获取要修改的用户的名称。我们不得不做一些愚蠢的控制层次遍历来获取数据,这是Web表单中令人讨厌的一部分。我们将发送方(初始化事件的控件)强制转换为dropdownlist,并获取它的当前选定值。最后,我们将其写入调试控制台。在应用程序中,您可能希望更新存储库中的域对象。

    我们通常不会像这样构建控件HTML。在ASPX标记上声明控件,然后将适当的数据绑定到它。使用中继器等@mason Ok-我以前从未使用过中继器。如果我弄明白了,我会做一些研究,然后再做报告。如果你刚刚学习ASP.NET,为什么你要从Web表单而不是MVC开始呢?我从过去几个夏天的实习经历中了解到一些ASP.NET,而公司使用的是Web表单而不是MVC。我正在做的项目是一个为期一学期的小组项目,我是唯一一个有网络应用经验的人。我不想同时教我自己和其他三个学生MVC,我只是使用WebForms,因为我对它很熟悉。如果有更多的时间和更多的知识,我会使用MVC。MVC比Web表单更容易学习,速度更快,更容易建立一个像样的体系结构,而且Web表单不会包含在ASP.NET的未来中。如果还来得及的话,我强烈鼓励你这么做。只要掌握一点C#和HTML知识,就很容易启动并运行。
    <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>
    
    DropDownList ddl = (DropDownList)sender;
    RepeaterItem item = (RepeaterItem)ddl.NamingContainer;
    HiddenField hiddenID = (HiddenField)item.FindControl("hiddenID");
    int ID = int.Parse(hiddenID.Value);
    
    <%@ 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>
    
    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; }
        }
    }