【问题标题】:How to get the checkbox value from a dynamically generated checkbox list in asp.net如何从asp.net中动态生成的复选框列表中获取复选框值
【发布时间】:2012-04-28 02:31:52
【问题描述】:

在 Web 表单中,我动态创建了一系列添加到 asp:placeholder 的复选框

//Generates the List of Entities that may be shared
        protected void GenerateEntityList(string agencyId, string agencyName)
        {
            var selectedAgency = UserFactory.GetAgencyAndSharedDataById(Convert.ToInt64(agencyId));

            entityContainer.Controls.Clear();

            //builds the entity list based upon entities in DB
            var currentEntities = UserFactory.GetEntityList();
            //add checkboxes
            entityContainer.Controls.Add(new LiteralControl("<input type='checkbox' id='selectAllCB' value='All'>Select All<br/><br/>"));
            foreach (var item in currentEntities)
            {
                CheckBox entityCheckBox = new CheckBox();
                int currentItem = item.EntityTypeId.GetValueOrDefault(0);
                entityCheckBox.Text = item.EntityName.ToString();

                entityCheckBox.CssClass = "am_Checkbox";
                entityContainer.Controls.Add(entityCheckBox);
                entityContainer.Controls.Add(new LiteralControl("<br/><br/>"));

                //mark checkboxes as checked if currently stored in the database
                if (selectedAgency.FirstOrDefault().SecurityDataShares != null && selectedAgency.FirstOrDefault().SecurityDataShares.Count > 0)
                {
                    foreach (var ce in selectedAgency.FirstOrDefault().SecurityDataShares)
                    {
                        if (ce.EntityId == item.EntityId)
                        {
                            entityCheckBox.Checked = true;
                        }
                    }
                }
            }

创建后,用户可以进行选择或删除选择。单击更新时,我想返回/收集复选框中的值,以便我可以将它们重新插入数据库。

//get the text value of every checkbox 
protected void updateEnties()
{
    string receivingAgency = ReceivingAgencyID;
    long contributingAgency = QueryID;

    List<string> cbValues = new List<string>();
    foreach (CheckBox currentItem in entityContainer.Controls)
    {
        cbValues.Add(currentItem.Text);
    }
}

但是,当我尝试遍历集合时,我没有得到任何返回,这使我相信我错误地调用了控件,或者它由于回发而被破坏。 我应该使用其他控件(如 Listbox 控件)而不是将这些元素写入占位符吗?

有人可以为我提供一些关于如何检索复选框值的指导吗?

【问题讨论】:

    标签: c# asp.net checkbox


    【解决方案1】:

    有两种思想流派;一,您需要重新创建为初始视图创建的控件层次结构,以便页面可以将视图状态和表单值恢复到控件树中,或者二,您可以使用低技术解决方案并简单地获取表单集合中的值。

    我个人喜欢选项二,它相对容易处理,因为看起来您已经在使用LiteralControl 手动创建 HTML。只需提供一个 name 在您手动创建的输入标签之间共享的属性(为简洁起见,此处显示的示例,这可能不是您将要做的):

    entityContainer.Controls.Add(new LiteralControl("<input type='checkbox' name='mySharedName' />");
    

    然后,要获取值就这么简单:

     var selectedValues = Request.Form["mySharedName"];
     // This is now a comma separated list of values that was checked
    

    那么你就不用担心控制树的状态了。

    【讨论】:

    • 这似乎工作正常,但 Request.Form 只返回选定表单元素的“on”值关于如何取回该值的任何建议?示例 Checkbox foo 已检查如何获取 'var selectedValues' 以在数组中显示 foo vs on
    • 消除过程。在 Z 项中,如果您知道 X 已检查,则 (Z - X) 不检查。但是,当您只想知道检查了哪些项目时,此过程会更好。
    • 啊,这是我的问题。我的列表是使用 linq 动态生成的,并按字母顺序排序,不一定是它在数据库中的存储方式或固定值我真的需要派生两者,以便我可以交叉引用以确保捕获正确的检查元素
    • 如果你想要所有的值,你总是可以渲染一组&lt;input type="hidden" value="X" name="anotherSharedKey" /&gt;,不管检查状态如何。
    • 正确的,如果你有一个隐藏的字段,这些都将被发送回服务器。所以Request.Form["anotherSharedKey"] 会告诉你所有可能的选择,然后mySharedName 逗号列表会告诉你哪些被选中。
    【解决方案2】:

    听起来您只需使用CheckBoxList 并将您的结果集绑定到它,就可以让生活变得更轻松。这实际上会消除对任何动态内容的需求。

    <asp:CheckBoxList ID="CheckList1" runat="server" DataTextField="TextColumn" DataValueField="ValueColumn" ...>
    

    如果这不是一个选项,那么您需要在每次回发后重新创建控件。有几种方法可以做到这一点。

    简单的方法

    查看DynamicControlsPlaceHolder 控件。这是一个有用的小控件,它负责在幕后持久化动态内容。我建议使用此选项,因为它消除了动态创建内容的所有痛苦。

    手动方式

    OnInit 期间重新创建控件。只需确保为控件分配相同的 ID,以便 ViewState 可以重新填充选择:

    protected override void OnInit(EventArgs e)
    {
        var chk = new CheckBox { ID = "chkBox1" };                 
        PlaceHolder1.Controls.Add(chk);
    
        base.OnInit(e);
    }    
    

    在回发后重新创建控件后,您应该能够像这样访问值:

    foreach (CheckBox chk in PlaceHolder1.Controls.OfType<CheckBox>())
    {
        if (chk.Checked)
        {
    
        }     
    }
    

    【讨论】:

    • 对不起,我在这里遗漏了一些东西,这看起来很直接,但是 foreach 会在我的点击事件方法中正确吗?所以允许我遍历列表?上面的 foreach 是否应该嵌套在另一个 foreach 语句中。我问上面的代码引用了一个具有选定属性的对象项?
    • 抱歉,忘记更新示例的那部分。应该检查。我最初的示例是使用 CheckBoxList。我更新了我的答案,所以现在应该更清楚了:)
    【解决方案3】:

    感谢大家的建议。基于这是如何实现的,我将答案归功于 Tejs,因为他让我沿着这个解决方案的思路走下去。在这个项目中,由于我构建列表和验证选中元素的方式,我需要使用复选框与复选框列表控件。挑战来自于 asp.net 如何生成复选框控件以及允许向控件插入属性(名称、值等)的限制

    因此,为了从代码生成的复选框中捕获值,我执行了以下操作:

    在 aspx 文件中,我添加了一个隐藏的输入字段并分配了一个 runat=server 标记

     <input id="cbEntityList" type="hidden" runat="server" value="" />
    

    Tejs 解决方案与此类似,但我不喜欢为每个复选框添加隐藏字段的想法,因为这看起来像页面中的很多元素。

    然后,我修改了复选框代码生成部分,将我的对象的唯一标识符作为 Id 包含在内。 ID 在 html 中呈现为 name 属性,因此这使我可以使用 javascript /jQuery 检索一些东西

    因此,在我将构建复选框的 foreach 语句中,我添加了以下行

    entityCheckBox.ID = item.EntityId.ToString();
    

    最后,我使用 jQuery 来迭代页面中的复选框并返回一个仅包含选中项的字符串数组。

    这将根据选中的复选框向隐藏字段填充一个值,例如 (0,1,2,3,4)。

    $('#btnUpdateEntities').click(function (event) {
            var fields;
            $(':checkbox:checked').each(function () {
                var txt = $("input[name='cbEntityList']");
    
                fields = ($(':checkbox:checked').map(function () {
                    return this.name;
                }).get().join(","));
    
                $(txt).val(fields);
            });
        });
    

    然后我可以访问后面代码中的值数组:

    string voo = cbEntityList.Value;
    

    希望这对任何感兴趣的人有所帮助。

    【讨论】:

      【解决方案4】:

      对于这种事情,您应该使用 OO 原则来组合实现。在这种情况下,您可能应该构建自己的 CheckBoxCollection(继承自正确的接口/类)。它将简化代码并使其更具分隔性和可扩展性。

      其中一个实现细节是处理您描述的情况:添加一个单击处理程序,该处理程序添加到视图状态/会话/任何内容,您应该能够看到您的测试工具/用户已选中/未选中的任何内容一目了然。

      另一个要点:你不应该再使用
      标签进行布局,特别是如果你已经在使用 CSS。您可以确保 checkboxen 是您需要的任何显示类型(在这种情况下是块?),然后在您已经装饰控件的 CSS 类中设置它。

      tl;dr:我没有时间在代码中举一个例子,但基本的想法是你应该有一个 CheckBoxCollection() (根据你的喜好)保留它的 CheckBox()s' .Checked从行动到行动的状态。

      【讨论】:

      • 感谢关于“
        ”标签的建议,我删除了它们并更新了 CSS 以支持布局。您的建议超出了我的需要,因为我不想使用点击处理程序来检查和更新每次点击时的视图状态/会话。
      • @JamesJohnson 这不是,真的 - 这是做这件事的“正确”方式。我们的职业有时会产生像我这样受苦的人,部分原因是更多的人只是把垃圾代码扔在那里,然后永远留在生产环境中。一个适当分解的解决方案是一个快乐的解决方案。特别是当你有定制的东西时,当事物被适当地抽象时,以各种方式进行管理会更容易。很高兴您认为可以在不以某种方式实际反驳它的情况下对我的回答投反对票;你很成熟。
      • @rlcrews 为什么不想为它添加处理程序?这样做很简单,并使您的代码更易于理解/维护。如果你拼凑一些“有效”但不是“标准”的东西,你会让代码库中落后于你的任何人感到困惑和沮丧。
      • @Tonweight:我明白你在说什么,但如果这是一种“需要一次”的情况,那就太过分了。如果它要在整个地方重复使用,那么当然,构建一个控件。尽管如此,已经有一个 CheckBoxList 控件看起来可以满足 OP 的需求。
      • @Tonweight 对于我的实现,我不想使用处理程序并将每个复选框选择贡献给视图状态。我完全尊重您对正确方法的看法,但我也认为还有其他替代解决方案也是正确的,在某些情况下可能是更好的选择。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-08
      • 1970-01-01
      相关资源
      最近更新 更多