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

时间:2017-04-19 01:26:51

标签: c# asp.net drop-down-menu

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

| 姓名 | 电子邮件 | CurrentUserGroup | ChangeUserGroup |

每行的ChangeUserGroup列都有一个DropDownList控件,其中包含3个选项(student,advisor,admin),在SelectedIndexChanged事件中,每行都更新它的用户的userGroup。

几个星期前我有这个工作,但从来没有做过改变,我丢失了它们,不记得我是如何工作的。

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

  1. 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() });
    }
    
  2. 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>
    
    1. 更改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;
      }
      }
      
    2. 但是,此代码无效。它正确呈现页面上的控件,但SelectedItemChanged永远不会触发。 AutoPostBack已启用。我认为这是因为控件实际上并没有正确地添加到页面中,而服务器也看不到它们。

      任何人都知道如何做到这一点?

2 个答案:

答案 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的烦人部分。我们将发送者(启动事件的控件)转换为下拉列表并获取其当前选定的值。最后,我们将其写入调试控制台。在您的应用程序中,您可能希望更新存储库中的域对象。