2

在 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 控件)而不是将这些元素写入占位符吗?

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

4

4 回答 4

4

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

我个人喜欢选项二,它相对容易处理,因为看起来你已经在手动创建 HTML 了LiteralControl。只需提供一个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

然后你不必担心控制树状态。

于 2012-04-16T18:39:33.120 回答
2

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

<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)
    {

    }     
}
于 2012-04-16T20:02:31.913 回答
0

感谢大家的建议。基于这是如何实现的,我将答案归功于 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;

希望这可以帮助任何感兴趣的人。

于 2012-04-17T21:38:01.290 回答
-1

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

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

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

tl;博士:我没有时间在代码中举一个例子,但基本的想法是你应该有一个 CheckBoxCollection() (根据你的喜好)保留它的 CheckBox()s' .Checked states from action采取行动。

于 2012-04-16T18:54:49.530 回答