You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET Repeater中遍历绑定的C#字典值?

解决ASP.NET Web Forms Repeater遍历字典生成带Optgroup的MaterializeCSS Select

刚从PHP转ASP.NET Web Forms确实会有思维转换的问题,你的核心需求是用Repeater遍历IDictionary<string, string[]>,生成带optgroup的原生<select>来适配MaterializeCSS,原来的代码主要有两个问题:

  • <%# %>是数据绑定表达式,只能返回单个值/结果,不能直接写foreach循环语句
  • Eval("Value")返回的是object类型,无法直接遍历,需要先强转为目标类型

下面给你两种可行的解决方案,都是基于原生HTML控件(避免使用自带样式的WebControls):

方案1:嵌套Repeater(推荐,控件化思维更符合Web Forms)

这种方式用外层Repeater处理optgroup,内层Repeater处理每个分组下的option,结构清晰,易维护。

前台.aspx代码

<div class="input-field">
    <asp:Repeater runat="server" ID="rptOptGroupSelect">
        <HeaderTemplate>
            <select id="mySelect" runat="server">
        </HeaderTemplate>
        <ItemTemplate>
            <optgroup label='<%# Eval("Key") %>'>
                <%-- 内层Repeater绑定当前分组的字符串数组 --%>
                <asp:Repeater runat="server" DataSource='<%# ((KeyValuePair<string, string[]>)Container.DataItem).Value %>'>
                    <ItemTemplate>
                        <option value='<%# ((string)Container.DataItem).ToLower() %>'>
                            <%# Container.DataItem %>
                        </option>
                    </ItemTemplate>
                </asp:Repeater>
            </optgroup>
        </ItemTemplate>
        <FooterTemplate>
            </select>
            <label for="mySelect">Please select something</label>
        </FooterTemplate>
    </asp:Repeater>
</div>

后台.cs绑定代码

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        // 模拟你的字典数据源
        var dictData = new Dictionary<string, string[]>
        {
            { "Fruits", new[] { "Apple", "Banana", "Orange" } },
            { "Vegetables", new[] { "Carrot", "Spinach", "Tomato" } }
        };

        rptOptGroupSelect.DataSource = dictData;
        rptOptGroupSelect.DataBind();
    }
}

方案2:后台绑定方法生成HTML字符串

如果不想用嵌套控件,可以在后台写一个方法,接收分组的字符串数组,直接生成option的HTML代码,前台调用这个方法。

前台.aspx代码

<div class="input-field">
    <asp:Repeater runat="server" ID="rptOptGroupSelect">
        <HeaderTemplate>
            <select id="mySelect" runat="server">
        </HeaderTemplate>
        <ItemTemplate>
            <optgroup label='<%# Eval("Key") %>'>
                <%# GenerateOptions((string[])Eval("Value")) %>
            </optgroup>
        </ItemTemplate>
        <FooterTemplate>
            </select>
            <label for="mySelect">Please select something</label>
        </FooterTemplate>
    </asp:Repeater>
</div>

后台.cs方法代码

protected string GenerateOptions(string[] options)
{
    if (options == null || options.Length == 0) return string.Empty;

    var sb = new StringBuilder();
    foreach (var opt in options)
    {
        // 注意HTML编码,防止XSS风险
        var safeOpt = Server.HtmlEncode(opt);
        sb.AppendFormat("<option value='{0}'>{1}</option>", safeOpt.ToLower(), safeOpt);
    }
    return sb.ToString();
}

// 绑定数据源的代码和方案1一致
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        var dictData = new Dictionary<string, string[]>
        {
            { "Fruits", new[] { "Apple", "Banana", "Orange" } },
            { "Vegetables", new[] { "Carrot", "Spinach", "Tomato" } }
        };

        rptOptGroupSelect.DataSource = dictData;
        rptOptGroupSelect.DataBind();
    }
}

关键注意事项(MaterializeCSS适配)

MaterializeCSS不会自动渲染原生<select>,必须手动初始化,在页面底部添加JS代码:

<script>
    document.addEventListener('DOMContentLoaded', function() {
        var elems = document.querySelectorAll('select');
        var instances = M.FormSelect.init(elems);
    });
</script>

如果页面用了UpdatePanel,还要在异步回发完成后重新初始化:

protected void UpdatePanel1_Load(object sender, EventArgs e)
{
    ScriptManager.RegisterStartupScript(this, GetType(), "initSelect", "$('select').formSelect();", true);
}

内容的提问来源于stack exchange,提问作者3x071c

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:19:33