如何在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
相关产品推荐
相关产品推荐

