【问题标题】:Adding attribute to checkbox list at runtime在运行时将属性添加到复选框列表
【发布时间】:2014-01-07 06:03:14
【问题描述】:

所以我有一些代码可以根据 XML 输入文件动态创建 ASP.NET 表单。我正在尝试在运行时向控件添加属性,但列表项出现了一些奇怪的问题。

我的服务器端代码如下所示:

Me.radioButtonList = New RadioButtonList()
Me.dropDownList = New DropDownList()
Me.listControl = Nothing
If controlType = "dropdown" Then
    Me.listControl = Me.dropDownList
Else
    Me.listControl = Me.radioButtonList
End If
For Each ansElement As Answer In strAnswers
    Dim newListItem = New ListItem(ansElement.AnswerText, ansElement.AnswerText)
    If ansElement.ActionID IsNot Nothing AndAlso ansElement.ActionID <> "" Then
        newListItem.Attributes.Add("actionID", ansElement.ActionID)
    End If
    Me.listControl.Items.Add(newListItem)
Next
Me.listControl.ID = controlID
Me.Controls.Add(Me.listControl)

问题是当我运行代码并渲染页面时,属性被添加到控件的正在进行的 span 标记中,而不是输入项本身。所以渲染的 HTML 最终看起来像这样。

<span actionID="1">
    <input id="lst_dynamic_MedIllnesses_0" name="ctl00$MainContentPlaceHolder$FormGenerator1$lst_dynamic_MedIllnesses$lst_dynamic_MedIllnesses_0" value="None" type="checkbox">
    <label for="lst_dynamic_MedIllnesses_0">None</label>
</span>

我需要做什么才能将 actionID 属性添加到实际的输入控件而不是 span 标签中?

谢谢!

【问题讨论】:

    标签: html asp.net forms


    【解决方案1】:

    我想你说的是 RadioButtonList。它的问题在于它使用 RadioButton 控件,并且它具有 3 个属性属性 - Attributes、InputAttributes 和 LabelAttributes。它们中的每一个都用于特定的 html 元素。

    RadioButtonList 的问题在于它只使用 Attributes 属性,而不使用 InputAttributes。这是 RadioButtonList.RenderItem 方法的代码:

    protected virtual void RenderItem(ListItemType itemType, int repeatIndex, RepeatInfo repeatInfo, HtmlTextWriter writer)
    {
      if (repeatIndex == 0)
      {
        this._cachedIsEnabled = this.IsEnabled;
        this._cachedRegisterEnabled = this.Page != null && !this.SaveSelectedIndicesViewState;
      }
      RadioButton controlToRepeat = this.ControlToRepeat;
      int index1 = repeatIndex + this._offset;
      ListItem listItem = this.Items[index1];
      controlToRepeat.Attributes.Clear();
      if (listItem.HasAttributes)
      {
        foreach (string index2 in (IEnumerable) listItem.Attributes.Keys)
          controlToRepeat.Attributes[index2] = listItem.Attributes[index2];
      }
      if (!string.IsNullOrEmpty(controlToRepeat.CssClass))
        controlToRepeat.CssClass = "";
      ListControl.SetControlToRepeatID((Control) this, (Control) controlToRepeat, index1);
      controlToRepeat.Text = listItem.Text;
      controlToRepeat.Attributes["value"] = listItem.Value;
      controlToRepeat.Checked = listItem.Selected;
      controlToRepeat.Enabled = this._cachedIsEnabled && listItem.Enabled;
      controlToRepeat.TextAlign = this.TextAlign;
      controlToRepeat.RenderControl(writer);
      if (!controlToRepeat.Enabled || !this._cachedRegisterEnabled || this.Page == null)
        return;
      this.Page.RegisterEnabledControl((Control) controlToRepeat);
    }
    

    controlToRepeat 就是那个 RadioButton,它只指定了 Attributes 属性而忽略了 InputAttributes。

    我可以建议修复它的方法 - 您可以创建继承 RadioButtonList 的新类,并使用它而不是默认值。这是该类的代码:

    public class MyRadioButtonList : RadioButtonList
    {
        private bool isFirstItem = true;
    
        protected override void RenderItem(ListItemType itemType, int repeatIndex, RepeatInfo repeatInfo, HtmlTextWriter writer)
        {
            if (isFirstItem)
            {
                // this.ControlToRepeat will be created during this first call, and then it will be placed into Controls[0], so  we can get it from here and update for each item.
                var writerStub = new HtmlTextWriter(new StringWriter());
                base.RenderItem(itemType, repeatIndex, repeatInfo, writerStub);
                isFirstItem = false;
            }
    
            var radioButton = this.Controls[0] as RadioButton;
    
            radioButton.InputAttributes.Clear();
            var item = Items[repeatIndex];
            foreach (string attribute in item.Attributes.Keys)
            {
                radioButton.InputAttributes.Add(attribute, item.Attributes[attribute]);                
            }
            // if you want to clear attributes for top element, in that case it's a span, then you need to call
            item.Attributes.Clear();
    
            base.RenderItem(itemType, repeatIndex, repeatInfo, writer);
    
        }
    }
    

    稍微说明一下——它有 isFirstItem 属性,因为它使用的 RadioButton 控件是在第一次访问时在运行时创建的,所以我们需要先调用 RenderItem 才能更新 InputAttrubutes 属性。所以我们调用它一次并发送一些存根 HtmlTextWriter,所以它不会显示两次。之后,我们将这个控件作为 Controls[0] 获取,并为每个 ListItem 更新 InputAttributes 值。

    PS。抱歉,我没有使用 VB.Net,所以控件是用 C# 编写的

    【讨论】:

    • CheckboxList 项是否存在同样的问题,因此也需要覆盖?
    • 那么我该如何防止它在两个地方呈现属性呢?现在我得到了 span 标签和 input 标签的属性。所以这导致了另一组问题。
    • 是的,CheckBoxList 也有同样的问题。但是,与使用 RadioButton 控件作为项目的 RadioButtonList 不同,CheckBoxList 使用 CheckBox 控件。 RadioButton 继承了 CheckBox。
    • 我更新了代码,其中包含如何从 span 中删除属性的示例。基本上你只需要调用 item.Attributes.Clear();将它们复制到 InputAttributes 之后。
    • 太棒了,这对我来说非常完美!很好的答案,感谢所有帮助!我很奇怪 RadioButtonList 和 CheckBoxList 默认不公开属性。似乎需要很多东西。
    猜你喜欢
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多