使用Linq表达式在扩展方法中有趣(?)
发布时间:2020-12-16 03:47:42 所属栏目:asp.Net 来源:网络整理
导读:我写了一个 HtmlHelper表达式,我花了很多时间将标题标签放入我的下拉列表中,如下所示: public static HtmlString SelectForTModel,TProperty,TListItem( this HtmlHelperTModel htmlHelper,ExpressionFuncTModel,TProperty expression,IEnumerableTListItem
我写了一个
HtmlHelper表达式,我花了很多时间将标题标签放入我的下拉列表中,如下所示:
public static HtmlString SelectFor<TModel,TProperty,TListItem>( this HtmlHelper<TModel> htmlHelper,Expression<Func<TModel,TProperty>> expression,IEnumerable<TListItem> enumeratedItems,string idPropertyName,string displayPropertyName,string titlePropertyName,object htmlAttributes) where TModel : class { //initialize values var metaData = ModelMetadata.FromLambdaExpression(expression,htmlHelper.ViewData); var propertyName = metaData.PropertyName; var propertyValue = htmlHelper.ViewData.Eval(propertyName).ToStringOrEmpty(); var enumeratedType = typeof(TListItem); //build the select tag var returnText = string.Format("<select id="{0}" name="{0}"",HttpUtility.HtmlEncode(propertyName)); if (htmlAttributes != null) { foreach (var kvp in htmlAttributes.GetType().GetProperties() .ToDictionary(p => p.Name,p => p.GetValue(htmlAttributes,null))) { returnText += string.Format(" {0}="{1}"",HttpUtility.HtmlEncode(kvp.Key),HttpUtility.HtmlEncode(kvp.Value.ToStringOrEmpty())); } } returnText += ">n"; //build the options tags foreach (TListItem listItem in enumeratedItems) { var idValue = enumeratedType.GetProperties() .FirstOrDefault(p => p.Name == idPropertyName) .GetValue(listItem,null).ToStringOrEmpty(); var titleValue = enumeratedType.GetProperties() .FirstOrDefault(p => p.Name == titlePropertyName) .GetValue(listItem,null).ToStringOrEmpty(); var displayValue = enumeratedType.GetProperties() .FirstOrDefault(p => p.Name == displayPropertyName) .GetValue(listItem,null).ToStringOrEmpty(); returnText += string.Format("<option value="{0}" title="{1}"",HttpUtility.HtmlEncode(idValue),HttpUtility.HtmlEncode(titleValue)); if (idValue == propertyValue) { returnText += " selected="selected""; } returnText += string.Format(">{0}</option>n",displayValue); } //close the select tag returnText += "</select>"; return new HtmlString(returnText); } ……这很有效,但有时我想走得更远.我想自定义这个野兽的id,display和title piece,而不必写出html.例如,如果我在模型中有一些类,如下所示: public class item { public int itemId { get; set; } public string itemName { get; set; } public string itemDescription { get; set; } } public class model { public IEnumerable<item> items { get; set; } public int itemId { get; set; } } 在我看来,我可以写: @Html.SelectFor(m => m.itemId,Model.items,"itemId","itemName","itemDescription",null) …我会得到一个带有标题属性等的精彩下拉列表.只要枚举项具有与我想要显示它们完全相同的属性,这就很棒了.但我真正喜欢的是: @Html.SelectFor(m => m.itemId,id=>id.itemId,disp=>disp.itemName,title=>title.itemName + " " + title.itemDescription,null) …在这种情况下,选项上的title属性是itemName属性和itemDescription属性的串联.我承认lambda表达式的元级别,Linq函数让我有点头晕.有人能指出我正确的方向吗? 最终结果对于那些好奇的人,以下代码使我可以使用lambda表达式完全控制选择列表的ID,Title和DisplayText属性: public static HtmlString SelectFor<TModel,TProperty>> forExpression,Attribute<TListItem> idExpression,Attribute<TListItem> displayExpression,Attribute<TListItem> titleExpression,object htmlAttributes,bool blankFirstLine) where TModel : class { //initialize values var metaData = ModelMetadata.FromLambdaExpression(forExpression,HttpUtility.HtmlEncode(kvp.Value.ToStringOrEmpty())); } } returnText += ">n"; if (blankFirstLine) { returnText += "<option value=""></option>"; } //build the options tags foreach (TListItem listItem in enumeratedItems) { var idValue = idExpression(listItem).ToStringOrEmpty(); var displayValue = displayExpression(listItem).ToStringOrEmpty(); var titleValue = titleExpression(listItem).ToStringOrEmpty(); returnText += string.Format("<option value="{0}" title="{1}"",displayValue); } //close the select tag returnText += "</select>"; return new HtmlString(returnText); } public delegate object Attribute<T>(T listItem); 解决方法
如果您不需要各个选项的title属性,您的代码可以简化为:
public static HtmlString SelectFor<TModel,TIdProperty,TDisplayProperty,TListItem>( this HtmlHelper<TModel> htmlHelper,Expression<Func<TListItem,TIdProperty>> idProperty,TDisplayProperty>> displayProperty,object htmlAttributes ) where TModel : class { var id = (idProperty.Body as MemberExpression).Member.Name; var display = (displayProperty.Body as MemberExpression).Member.Name; var selectList = new SelectList(enumeratedItems,id,display); var attributes = new RouteValueDictionary(htmlAttributes); return htmlHelper.DropDownListFor(expression,selectList,attributes); } 并像这样使用: @Html.SelectFor( m => m.itemId,id => id.itemId,disp => disp.itemName,null ) 如果你需要title属性,那么你必须实现DropDownList帮助器手动完成的所有操作,这可能会非常麻烦.以下是所有功能的一小部分示例: public static class HtmlExtensions { private class MySelectListItem : SelectListItem { public string Title { get; set; } } public static HtmlString SelectFor<TModel,Func<TListItem,string> titleProperty,object htmlAttributes ) where TModel : class { var name = ExpressionHelper.GetExpressionText(expression); var fullHtmlName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name); var select = new TagBuilder("select"); var compiledDisplayProperty = displayProperty.Compile(); var compiledIdProperty = idProperty.Compile(); select.GenerateId(fullHtmlName); select.MergeAttributes(new RouteValueDictionary(htmlAttributes)); select.Attributes["name"] = fullHtmlName; var selectedValue = htmlHelper.ViewData.Eval(fullHtmlName); var options = from i in enumeratedItems select ListItemToOption( ItemToSelectItem(i,selectedValue,compiledIdProperty,compiledDisplayProperty,titleProperty) ); select.InnerHtml = string.Join(Environment.NewLine,options); return new HtmlString(select.ToString(TagRenderMode.Normal)); } private static MySelectListItem ItemToSelectItem<TListItem,TDisplayProperty>(TListItem i,object selectedValue,TIdProperty> idProperty,TDisplayProperty> displayProperty,string> titleProperty) { var value = Convert.ToString(idProperty(i)); return new MySelectListItem { Value = value,Text = Convert.ToString(displayProperty(i)),Title = titleProperty(i),Selected = Convert.ToString(selectedValue) == value }; } private static string ListItemToOption(MySelectListItem item) { var builder = new TagBuilder("option"); builder.Attributes["value"] = item.Value; builder.Attributes["title"] = item.Title; builder.SetInnerText(item.Text); if (item.Selected) { builder.Attributes["selected"] = "selected"; } return builder.ToString(); } } 然后像这样使用: @Html.SelectFor( m => m.itemId,title => title.itemName + " " + title.itemDescription,null ) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- asp.net-mvc – 基于MVC角色的路由
- asp.net-core – Razor模板中的特殊字符未正确编码
- asp.net-mvc-4 – 如何在MVC 4中创建自定义WebSecurity.Log
- ASP.NET Identity简介及简单使用
- asp.net-mvc – 如何在多个Asp.net MVC应用程序中使用通用布
- asp.net-mvc-2 – 查找要在ASP.NET MVC项目上使用的授权框架
- ASP.NET ReportViewer Google Chrome CPU使用情况
- asp.net-mvc – ASP.NET MVC:访问集合中项目的ModelMetada
- asp.net-mvc – ASP.NET MVC中的动态(运行时生成)窗体
- .net – 如何在MVC 5中设置本地授权认证?
推荐文章
站长推荐
- asp.net-mvc-4 – 没有为此对象定义的无参数构造
- asp.net-core – 如何在启动时将数据放入MemoryC
- asp.net-mvc-3 – 带Razor的条件显示元素
- 在ASP.NET中的Response.Redirect中传递cookie
- asp.net-mvc – ASP.NET MVC 3确定会话状态(新的
- asp.net-mvc – 如何在ASP MVC中编码完整的URL字
- ASP.NET MVC 3.0部分内部和外部表单具有不显眼的
- asp.net-mvc – HttpContext中需要什么来允许For
- asp.net-mvc – 使用Entity Framework在控制器中
- 在ASP.NET中生成图像缩略图?
热点阅读