在MVC2.0中使用模板化帮助器我遇到了一个dillema,如何让项目填充下拉列表。
我使用[UIHint(BadgesDropDown)]
属性,但是如果控制器将它们放在ViewData中,我将如何在不违反MVC模式的情况下获取列表项? BadgesDropDown.ascx
是否应该调用助手来获取它们?
现在我要去:
BadgesDropDown.ascx
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%= Html.DropDownList("", ViewData["Badges"] as IEnumerable<SelectListItem>)%>
控制器
ViewData["Badges"] = new SelectList(SiteRepository.GetBadges(), "RowKey", "BadgeName");
这是要走的路吗?
答案 0 :(得分:2)
最近有很多关于这个话题的讨论。日期,日期范围和多选复选框列表会遇到类似的包版广告。您可能希望在任何地方使用丰富的html控件。我一直在试验子ViewModels的概念,我认为解决方案比我尝试的其他方法更清晰。
基本概念是您定义一个与自定义EditorTemplate紧密耦合的小视图模型。
在您的示例中,我们将从一个(子)ViewModel开始,该ViewModel特定于单个选择列表:
public class SelectModel
{
#region SelectModel(string value, IEnumerable<SelectListItem> items)
public SelectModel(string value, IEnumerable<SelectListItem> items)
{
_value = value;
Items = new List<SelectListItem>(items);
_Select();
}
#endregion
// Properties
public List<SelectListItem> Items { get; private set; }
public string Value
{
get { return _value; }
set { _value = value; _Select();}
}
private string _value;
// Methods
private void _Select()
{
Items.ForEach(x => x.Selected = (Value != null && x.Value == Value));
}
}
在想要使用下拉列表的视图模型中,您构成了选择模型(我们都使用视图模型,对吧?):
public class EmailModel
{
// Constructors
public EmailModel()
{
Priority = new SelectModel("normal", _ToPrioritySelectItems());
}
// Properties
public SelectModel Priority { get; set; }
// Methods
private IEnumerable<SelectListItem> _ToPrioritySelectItems()
{
List<SelectListItem> result = new List<SelectListItem>();
result.Add(new SelectListItem() { Text = "High", Value = "high" });
...
}
请注意,这是一个带有一组固定下拉项的简单示例。如果它们来自域层,则控制器将它们传递给ViewModel。
然后在Shared / EditorTemplates
中添加编辑器模板SelectModel.ascx<%@ Control Inherits="System.Web.Mvc.ViewUserControl<SelectModel>" %>
<div class="set">
<%= Html.LabelFor(model => model) %>
<select id="<%= ViewData.ModelMetadata.PropertyName %>_Value" name="<%=ViewData.ModelMetadata.PropertyName %>.Value">
<% foreach (var item in Model.Items) { %>
<%= Html.OptionFor(item) %>
<% } %>
</select>
</div>
注意:OptionFor是一个自定义扩展,用于执行明显的
这里的技巧是使用默认ModelBinder期望的复合格式设置id和name。在我们的示例“Priority.Value”中。因此,直接设置定义为SelectModel的一部分的基于字符串的Value属性。如果我们需要重新显示表单,setter会负责更新Items列表以设置默认选择选项。
这种“儿童视图模型”方法真正发挥作用的是更复杂的“控制标记片段”。我现在有了子视图模型,它们遵循类似的方法用于MultiSelect列表,开始/结束日期范围和日期+时间组合。
一旦你沿着这条路走下去,下一个显而易见的问题就变成了验证。
我最终让我的所有孩子ViewModel实现了标准接口:
public interface IValidatable
{
bool HasValue { get; }
bool IsValid { get; }
}
然后,我有一个自定义ValidationAttribute:
public class IsValidAttribute : ValidationAttribute
{
// Constructors
public IsValidAttribute()
{
ErrorMessage = "(not valid)";
}
// Properties
public bool IsRequired { get; set; }
// Methods
private bool Is(object value)
{
return value != null && !"".Equals(value);
}
public override bool IsValid(object value)
{
if (!Is(value) && !IsRequired)
return true;
if (!(value is IValidatable))
throw new InvalidOperationException("IsValidAttribute requires underlying property to implement IValidatable");
IValidatable validatable = value as IValidatable;
return validatable.IsValid;
}
}
现在,您可以像使用任何标量属性一样将属性放在基于子ViewModel的属性上:
[IsValid(ErrorMessage = "Please enter a valid start date/time")]
public DateAndTimeModel Start { get; set; }
答案 1 :(得分:0)
在MVC 2中,一个很棒的新方法......如果使用它依赖于所有属性数据。
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<glossaryDB.EntityClasses.AssociationEntity>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Association: Edit
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
<h3>Association: Edit</h3>
<% using (Html.BeginForm()) { %>
<fieldset style="padding: 1em; margin: 0; border: solid 1px #999;">
<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
<%= Html.EditorForModel() %>
<input type="submit" value=" Submit " />
</fieldset>
<% } %>
<p><%= Html.ActionLink("Details", "Index") %></p>
</asp:Content>
为此,有两种选择。 UIHint必须提供数据源或控制器必须。如果UIHint确实如此,那么提供给下拉列表的数据是固定的。另一个选项是控制器,它允许我们使用所需的不同数据集切换下拉数据。
我发现了一些相关的例子:
书呆子晚餐
[1]:codeclimber.net.nz的searcch以及如何创建一个dropdownlist-with-asp.net-mvc [2]:bradwilson.typepad.com和templates-part-5-master-page-templates
答案 2 :(得分:-1)
我按照上面的例子实现了解决方案。需要注意的一点是,助手应该只使用提供给他们的数据,请参阅View dependency
最佳做法是编写Html 帮助者不知道控制器和 上下文。他们应该做好自己的工作 仅基于提供的数据 来电者。
我同意上述声明。与常规的ASP.Net开发相比,只需要做很多工作。