如何创建自定义 Html.ControlFor
本文关键字:自定义 Html ControlFor 创建 何创建 | 更新日期: 2023-09-27 17:55:12
我有一个名为Entity
的类
public class Entity
{
public string Name { get; set; }
public Location Place { get; set; }
}
还有一类叫Location
public class Location
{
public string Country { get; set; }
public string State { get; set; }
public string City { get; set; }
}
一个Entity
包含一个Location
,所以我想为Location
生成 3 个下拉列表。
- 国家
- 州
- 城市
我可以像手动一样做
@Html.DropDownListFor(o => o.Country, new [] { new SelectListItem() { Text = "United States", Value="US" } })
<br />
@Html.DropDownListFor(o => o.State, new [] { new SelectListItem() { Text = "Some State", Value="SS" } })
<br />
@Html.DropDownListFor(o => o.City, new[] { new SelectListItem() { Text = "Some city", Value = "City" } })
但是我的网站上有几个地方需要完全相同的 3 个下拉菜单,例如 Restaurant
、Hotel
和其他也有Location
的类。我试图制作一个启动新表单的部分视图,但我得到了一个例外:
传递到字典中的模型项的类型为"TestMVC3Razor.Controllers.Entity",但此字典需要类型为"TestMVC3Razor.Controllers.Location"的模型项,代码如下:
@model TestMVC3Razor.Controllers.Entity
@using (Html.BeginForm())
{
@Html.Partial("LocationSelector", Model.Place)
<br />
<input type="submit" value="Submit" />
}
部分观点是
@model TestMVC3Razor.Controllers.Location
@using (Html.BeginForm())
{
@Html.DropDownListFor(o => o.Country, new [] { new SelectListItem() { Text = "United States", Value="US" } })
<br />
@Html.DropDownListFor(o => o.State, new [] { new SelectListItem() { Text = "Some State", Value="SS" } })
<br />
@Html.DropDownListFor(o => o.City, new[] { new SelectListItem() { Text = "Some city", Value = "City" } })
}
这显然不应该起作用,但我想做类似的事情,像这样的助手将是完美的
@Html.LocationSelectFor(o => o.Location)
但是我该怎么做呢?我需要生成3 dropdowns
,当我发布到操作时,我需要获取具有出价值的对象。
public ActionResult(Location loc)
{
var x = String.Format("{0}, {1} - {2}", loc.City, loc.Country, loc.State);
}
如何使此助手在发布时创建 3 个下拉列表并绑定值?
只需在 HtmlHelper 中创建自己的扩展:
public static HtmlHelperExtensions {
public static MvcString LocationSelectFor<TModel, TProperty>(this HtmlHelper<TModel> helper, System.Linq.Expressions.Expression<Func<TModel,TProperty>> expression) {
// examine expression and build html
}
}
诀窍是看表情。 这篇博文应该能帮助你入门:http://geekswithblogs.net/Madman/archive/2008/06/27/faster-reflection-using-expression-trees.aspx
或者,您可以为 Location 类创建编辑器模板。 只需谷歌搜索 asp.net mvc 编辑器模板。 http://www.codecapers.com/post/Display-and-Editor-Templates-in-ASPNET-MVC-2.aspx
就个人而言,我会坚持使用编辑器模板,因为您可以更改视图而无需通常重新编译。
您可以按照此示例使用表达式和表达式主体
从 Lambda 属性表达式获取自定义属性
或者只是使用字符串表达式并按照此处 http://www.joelscode.com/post/Use-MVC-Templates-with-Dynamic-Members-with-custom-HtmlHelper-Extensions.aspx 进行操作
按照xixonia的小提示,我得到了我需要的东西。
@Html.EditorFor(o => o.Place, "LocationSelector",
new CreateLocation{ Country = "US", State = "A", City = "Y" })
我在下面有一个模板
Views
|- Shared
|- EditorTemplates
LocationSelector.cshtml
@model TestMVC3Razor.Controllers.CreateLocation
@using TestMVC3Razor.Controllers
@Html.DropDownListFor(o => o.Country, Model.CountryList)
<br />
@Html.DropDownListFor(o => o.State, Model.StateList)
<br />
@Html.DropDownListFor(o => o.City, Model.CityList)
然后我做了
public class CreateEntity
{
[Required]
public string Name { get; set; }
public CreateLocation Place { get; set; }
}
public class CreateLocation
{
public CreateLocation(Location location = null)
{
if (location != null)
{
Country = location.Country;
State = location.State;
City = location.City;
}
}
public string Country { get; set; }
public string State { get; set; }
public string City { get; set; }
public IEnumerable<SelectListItem> CountryList
{
get
{
var list = new[]
{
new SelectListItem() { Text = "US", Value = "US" },
new SelectListItem() { Text = "BR", Value = "BR" },
new SelectListItem() { Text = "ES", Value = "ES" },
};
var selected = list.FirstOrDefault(o => o.Value == Country);
if (selected != null)
{
selected.Selected = true;
}
return list;
}
}
public IEnumerable<SelectListItem> StateList
{
get
{
var list = new[]
{
new SelectListItem() { Text = "A", Value = "A" },
new SelectListItem() { Text = "B", Value = "B" },
new SelectListItem() { Text = "C", Value = "C" },
};
var selected = list.FirstOrDefault(o => o.Value == State);
if (selected != null)
{
selected.Selected = true;
}
return list;
}
}
public IEnumerable<SelectListItem> CityList
{
get
{
var list = new[]
{
new SelectListItem() { Text = "X", Value = "X" },
new SelectListItem() { Text = "Y", Value = "Y" },
new SelectListItem() { Text = "Z", Value = "Z" },
};
var selected = list.FirstOrDefault(o => o.Value == City);
if (selected != null)
{
selected.Selected = true;
}
return list;
}
}
}
还有我的控制器
public class HomeController : Controller
{
public ActionResult Index()
{
// can load data for edit
return View(new CreateEntity { Place = new CreateLocation(TempData["Location"] as Location) });
}
[HttpPost]
public ActionResult Index(Entity ent)
{
var loc = ent.Place;
var x = String.Format("{0} {1} {2}", loc.Country, loc.State, loc.City);
ViewBag.Result = x; // display selected values
TempData["Location"] = loc;
return Index();
}
}
我不知道这是否是最好的解决方案,但至少我可以打电话
@Html.EditorFor(o => o.Place, "LocationSelector", obj)
从任何地方,在我的网站上有一个默认的地方选择器。