使用嵌套 div 而不是表或流来渲染 RadioButtonList

Posted

技术标签:

【中文标题】使用嵌套 div 而不是表或流来渲染 RadioButtonList【英文标题】:Render RadioButtonList using nested divs instead of tables or flow 【发布时间】:2013-02-01 19:54:02 【问题描述】:

我正在 C#.NET 3.5 中以编程方式生成一个单选按钮列表,并使用 RadioButtonList 来执行此操作。但是,我觉得非常令人沮丧的是RepeatLayout 属性,它只能设置为FlowTable

表格用于表格数据,而不是用于显示表格。并且流没有帮助,因为它不适合造型。

我真正想要的是可以用 CSS 处理的 div 嵌套。这个可以吗?

一些例子来说明我在说什么和下面的示例代码。

流程示例

<span id="s1">
    <input id="s1_0" type="radio" value="Answer A" name="s1">
    <label for="s1_0">Answer A</label>
    <br>
    <input id="s1_1" type="radio" value="Answer B" name="s1">
    <label for="s1_1">Answer B</label>
</span>

表格示例

<table border="0" id="s1">
    <tbody>
        <tr>
            <td><input type="radio" value="Answer A" name="s1" id="s1_0"><label for="s1_0">Answer A</label></td>
        </tr>
        <tr>
            <td><input type="radio" value="Answer B" name="s1" id="s1_1"><label for="s1_1">Answer B</label></td>
        </tr>
    </tbody>
</table>

我真正想要的

<div id="s1">
    <div>
        <input type="radio" value="Answer A" name="s1" id="s1_0">
        <label for="s1_0">Answer A</label>
    </div>
    <div>
        <input type="radio" value="Answer B" name="s1" id="s1_1">
        <label for="s1_1">Answer B</label>
    </div>
</div>

我用来生成列表的 C# 代码

我知道无论解决方案是什么,都不会像这样快速简单,但我把它放在这里是为了让您了解我使用它的环境。

RadioButtonList rbl = new RadioButtonList  RepeatLayout = RepeatLayout.Table ;
foreach (ControlValue cv in MasterControl.listControlValues)

    rbl.Items.Add(new ListItem(cv.name, cv.value));

ControlContainer.Controls.Add(rbl);

【问题讨论】:

我还注意到 .NET 4.5 具有无序列表和有序列表选项,这要好得多。但在这里对我没有帮助:((使用 3.5) 如果你想限制 radioButtonList 我认为不可能在单独的 div 中显示 list-item。但是您可以将radion-buttongroup name 分开,并将每个radio-button 设置在您喜欢的位置 【参考方案1】:

我认为您应该寻找使用 CSS 的解决方法,而不是更改结构。即使我在这种结构上也遇到了一些问题,但我的设计团队轻松地解决了它。

【讨论】:

是的,这就是我在这种情况下要做的,只是因为时间限制。实际的样式不是问题。将 CSS 应用于表格很容易。问题是我们使用表格来显示不是表格数据的东西。对于任何使用屏幕阅读器的人来说,它也绝对是一场噩梦。【参考方案2】:

您可能希望使用WebControlAdapter 来更改RadioButtonList 的呈现方式。

以下是您案例的完整代码:

public class RadioButtonListAdapter : WebControlAdapter

    protected override void RenderBeginTag(htmlTextWriter writer)
    
        writer.RenderBeginTag("div");
    

    protected override void RenderEndTag(HtmlTextWriter writer)
    
        writer.RenderEndTag();
    

    protected override void RenderContents(HtmlTextWriter writer)
    
        var adaptedControl = (RadioButtonList) Control;
        int itemCounter = 0;

        writer.Indent++;
        foreach (ListItem item in adaptedControl.Items)
        
            var inputId = adaptedControl.ClientID + "_" + itemCounter++;

            // item div
            writer.RenderBeginTag("div");
            writer.Indent++;

                // input
                writer.AddAttribute("type", "radio");
                writer.AddAttribute("value", item.Value);
                writer.AddAttribute("name", adaptedControl.ClientID);
                writer.AddAttribute("id", inputId);

                if (item.Selected)
                
                    writer.AddAttribute("checked", "checked");
                

                writer.RenderBeginTag("input");
                writer.RenderEndTag();

                // label
                writer.AddAttribute("for", inputId);

                writer.RenderBeginTag("label");

                writer.Write(item.Value);

                writer.RenderEndTag();

            // div
            writer.Indent--;
            writer.RenderEndTag();
        
        writer.Indent--;
    

要将此适配器连接到您的应用程序,您有两种选择。首先是在页面 constructor 中以编程方式进行:

var adapters = Context.Request.Browser.Adapters;
var radioButtonListType = typeof(RadioButtonList).AssemblyQualifiedName;
var adapterType = typeof(RadioButtonListAdapter).AssemblyQualifiedName;
if (!adapters.Contains(radioButtonListType))

    adapters.Add(radioButtonListType, adapterType);

第二个选项是使用.browser 文件:

将新的Browser File 添加到您的项目中。它将驻留在App_Browsers 文件夹中。然后用以下声明替换内容:

<browsers>
    <browser refID="Default">
            <controlAdapters>
                <adapter controlType="System.Web.UI.WebControls.RadioButtonList" 
                         adapterType="<your namespace>.RadioButtonListAdapter" />
            </controlAdapters>
    </browser>
</browsers>

作为参考,您可以使用 ScottGu 的帖子 ASP.NET 2.0 Control Adapter Architecture 中的链接,它们可以为这个主题提供一个很好的基础。

还有一个开源的CSS Friendly Control Adapters 项目解决了默认 ASP.NET 控件的一些呈现问题。

【讨论】:

【参考方案3】:

对于 .net 4.5 >

你几乎可以得到那个 html,至少是使用 OrderedList(或 UnOrdered)的结构,然后使用 CSS 来获得你喜欢的样式。

<asp:RadioButtonList ID="rblTest" runat="server" TextAlign="Left" RepeatDirection="Vertical" RepeatLayout="OrderedList">
   <asp:ListItem Value="1" Text="Option 1"></asp:ListItem>
   <asp:ListItem Value="2" Text="Option 2"></asp:ListItem>
   <asp:ListItem Value="3" Text="Option 3"></asp:ListItem>
</asp:RadioButtonList>

这将呈现 html:

<ol id="rblTest">
    <li>
        <label for="rblTest_0">Option 1</label>
        <input id="rblTest_0" type="radio" name="rblTest" value="0">
    </li>
    <li>
        <label for="rblTest_1">Option 2</label>
        <input id="rblTest_1" type="radio" name="rblTest" value="0">
    </li>
    <li>
        <label for="rblTest_2">Option 2</label>
        <input id="rblTest_2" type="radio" name="rblTest" value="0">
    </li>
</ol>

如果您愿意,设置 TextAlign="Right" 会在输入之后为您提供标签。

这与您可以使用 div 进行设置一样接近,但是再次,用 div 包围整个列表并从该 div 设置 li 和标签 css,您应该被设置。

【讨论】:

以上是关于使用嵌套 div 而不是表或流来渲染 RadioButtonList的主要内容,如果未能解决你的问题,请参考以下文章

在特定 div 中创建反应模式而不是渲染主体

在存储过程中使用表变量而不是仅从表或视图中选择?

嵌套反应路由器组件不会在页面重新加载时加载/渲染?

使用书签但从表单而不是表或查询访问 Word

表单出现错误“预期的表或查询集,而不是 str”

用p标记 包括div标记 最后浏览器渲染出来的 却没在里面