asp.net – 用于DropDownList的MVC2 EditorTemplate
|
我在过去一周的大部分时间里都用到了MVC2的新模板功能。我很难试图让一个DropDownList模板工作。我一直在努力解决的最大问题是如何获取下拉列表的源数据到模板。我看到很多例子,您可以将源数据放在ViewData字典(ViewData [“DropDownSourceValuesKey”])中,然后在模板本身中检索它们(var sourceValues = ViewData [“DropDownSourceValuesKey”];)这有效,但是我做了不像一个愚蠢的字符串作为这个工作的lync引脚。 以下是我提出的一种方法,并希望对这种方法提出意见: 这是我的设计目标: >视图模型应包含下拉列表的源数据 这是我的查看型号: public class CustomerViewModel
{
[ScaffoldColumn(false)]
public String CustomerCode{ get; set; }
[UIHint("DropDownList")]
[DropDownList(DropDownListTargetProperty = "CustomerCode"]
[DisplayName("Customer Code")]
public IEnumerable<SelectListItem> CustomerCodeList { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public String PhoneNumber { get; set; }
public String Address1 { get; set; }
public String Address2 { get; set; }
public String City { get; set; }
public String State { get; set; }
public String Zip { get; set; }
}
我的视图模型具有CustomerCode属性,它是用户从值列表中选择的值。我有一个CustomerCodeList属性,它是可能的CustomerCode值的列表,并且是下拉列表的来源。我已经使用DropDownListTargetProperty创建了一个DropDownList属性。 DropDownListTargetProperty指向将根据生成的下拉列表中的用户选择(在本例中为CustomerCode属性)填充的属性。 请注意,CustomerCode属性具有[ScaffoldColumn(false)],这迫使发生器跳过生成的输出中的字段。 我的DropDownList.ascx文件将生成一个来自CustomerCodeList属性的源数据的下拉列表表单元素。生成的下拉列表将使用DropDownList属性中的DropDownListTargetProperty的值作为Id和Select表单元素的Name属性。所以生成的代码将如下所示: <select id="CustomerCode" name="CustomerCode"> <option>... </select> 这样做非常好,因为在提交表单时,MVC将从下拉列表中选择所需值填充目标属性,因为生成的下拉列表的名称是目标属性。我有点可视化,因为CustomerCodeList属性是CustomerCode属性的扩展。我将源数据与资源相结合。 这是我的控制器代码: public ActionResult Create()
{
//retrieve CustomerCodes from a datasource of your choosing
List<CustomerCode> customerCodeList = modelService.GetCustomerCodeList();
CustomerViewModel viewModel= new CustomerViewModel();
viewModel.CustomerCodeList = customerCodeList.Select(s => new SelectListItem() { Text = s.CustomerCode,Value = s.CustomerCode,Selected = (s.CustomerCode == viewModel.CustomerCode) }).AsEnumerable();
return View(viewModel);
}
这是我的DropDownListAttribute的代码: namespace AutoForm.Attributes
{
public class DropDownListAttribute : Attribute
{
public String DropDownListTargetProperty { get; set; }
}
}
这是我的模板代码(DropDownList.ascx): <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<SelectListItem>>" %>
<%@ Import Namespace="AutoForm.Attributes"%>
<script runat="server">
DropDownListAttribute GetDropDownListAttribute()
{
var dropDownListAttribute = new DropDownListAttribute();
if (ViewData.ModelMetadata.AdditionalValues.ContainsKey("DropDownListAttribute"))
{
dropDownListAttribute = (DropDownListAttribute)ViewData.ModelMetadata.AdditionalValues["DropDownListAttribute"];
}
return dropDownListAttribute;
}
</script>
<% DropDownListAttribute attribute = GetDropDownListAttribute();%>
<select id="<%= attribute.DropDownListTargetProperty %>" name="<%= attribute.DropDownListTargetProperty %>">
<% foreach(SelectListItem item in ViewData.Model)
{%>
<% if (item.Selected == true) {%>
<option value="<%= item.Value %>" selected="true"><%= item.Text %></option>
<% } %>
<% else {%>
<option value="<%= item.Value %>"><%= item.Text %></option>
<% } %>
<% } %>
</select>
我尝试使用Html.DropDownList帮助器,但是不允许我更改生成的Select元素的Id和Name属性。 注意:您必须覆盖DropDownListAttribute的DataAnnotationsModelMetadataProvider的CreateMetadata方法。这是代码: public class MetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes,Type containerType,Func<object> modelAccessor,Type modelType,string propertyName)
{
var metadata = base.CreateMetadata(attributes,containerType,modelAccessor,modelType,propertyName);
var additionalValues = attributes.OfType<DropDownListAttribute>().FirstOrDefault();
if (additionalValues != null)
{
metadata.AdditionalValues.Add("DropDownListAttribute",additionalValues);
}
return metadata;
}
}
那么你必须在Global.asax.cs的Application_Start中调用新的MetadataProvider: protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
ModelMetadataProviders.Current = new MetadataProvider();
}
那么,我希望这是有道理的,我希望这种方法可以节省你一些时间。我想要一些关于这种方法的反馈。有更好的方法吗? 解决方法我想我找到一个解决方案,使其工作时使用Html.EditorForModel();当使用EditorForModel()时,MVC使用Object.ascx循环遍历模型的所有属性,并为模型中的每个属性调用相应的模板。 ASP.Net MVC开箱即用的Object.ascx在代码中,但您可以创建自己的Object.ascx。只需在“共享视图”文件夹中创建一个EditorTemplates子文件夹。在那里创建一个Object.ascx文件(阅读这篇文章了解更多信息: http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html)这是我的Object.ascx: <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%@ Import Namespace="WebAppSolutions.Helpers" %>
<% if (ViewData.TemplateInfo.TemplateDepth > 1) { %>
<%= ViewData.ModelMetadata.SimpleDisplayText%>
<% }
else { %>
<% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm))) { %>
<% var htmlFieldName = Html.HtmlFieldNameFor(prop.PropertyName);%>
<% if (prop.HideSurroundingHtml) { %>
<%= Html.Editor(htmlFieldName)%>
<% }
else { %>
<div id="<%= htmlFieldName %>Container" class="editor-field">
<% if (!String.IsNullOrEmpty(Html.Label(prop.PropertyName).ToHtmlString())) { %>
<%= Html.Label(prop.PropertyName,Html.HtmlDisplayName(prop.PropertyName),prop.IsRequired)%>
<% } %>
<%= Html.Editor(prop.PropertyName,"",htmlFieldName)%>
<%= Html.ValidationMessage(prop.PropertyName,"*") %>
</div>
<% } %>
<% } %>
<%}%> 我的WebAppSolutions.Helpers中有一些托管代码用于HtmlFieldNameFor和HtmlDisplayName。这些帮助程序从应用于视图模型中的属性的属性中检索数据。 public static String HtmlFieldNameFor<TModel>(this HtmlHelper<TModel> html,String propertyName)
{
ModelMetadata modelMetaData = GetModelMetaData(html,propertyName);
return GetHtmlFieldName(modelMetaData,propertyName);
}
public static String HtmlDisplayName<TModel>(this HtmlHelper<TModel> html,propertyName);
return modelMetaData.DisplayName ?? propertyName;
}
private static ModelMetadata GetModelMetaData<TModel>(HtmlHelper<TModel> html,String propertyName)
{
ModelMetadata modelMetaData = ModelMetadata.FromStringExpression(propertyName,html.ViewData);
return modelMetaData;
}
private static String GetHtmlFieldName(ModelMetadata modelMetaData,string defaultHtmlFieldName)
{
PropertyExtendedMetaDataAttribute propertyExtendedMetaDataAttribute = GetPropertyExtendedMetaDataAttribute(modelMetaData);
return propertyExtendedMetaDataAttribute.HtmlFieldName ?? defaultHtmlFieldName;
}
使用EditorModelFor()得到这个工作的关键是这个(在上面的Object.ascx中应该是第20行): <%= Html.Editor(prop.PropertyName,htmlFieldName)%> prop.PropertyName是ViewModel中的属性,包含将成为DropDownList的数据列表。 htmlFieldName是DropDownList属性替换隐藏的属性的名称。合理? 我希望这可以帮助你。 (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – 有关视图模型和模型更新的一些子集的最佳实践
- asp.net-mvc – ASP.NET MVC JsonResult返回500
- ASP.Net:为什么我的按钮的点击/命令事件没有在转发器中绑定
- asp.net – .NET 4.0 ObjectCache的线程安全和范围管理
- ASP.NET表单中的Paypal表单
- asp.net – 使用CompareValidator控件将用户输入日期与今天
- 组合密钥资源REST服务
- 如何在asp.net c#中计算网站访问者数量
- Asp.net MVC – Jquery $.ajax错误回调没有返回responseJSO
- asp.net – 每个人如何存储连接字符串?
- asp.net核心 – ASP.Net MVC 6中使用Tag Helpers
- asp.net-mvc – KendoUI网格显示总记录数
- asp.net – ASPXGridView ClientSideEvents如何获
- asp.net-mvc – VS2012启用NuGet包恢复消失,缺少
- asp.net-mvc-3 – ASP.Net MVC 3重定向未经授权的
- asp.net – 当我禁用提交按钮以防止双击时,为什么
- asp.net-mvc – ASP.NET MVC获取具有特定配置文件
- asp.net – App_Code中的类无法通过Global.asax.
- 如何从ASP.NET中的母版页访问内容页面控件
- asp.net-mvc – 如何根据设备类型更改ASP.NET MV
