2011-05-05 98 views
1

我有一個類叫做Entity如何創建自定義的Html.ControlFor?

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一個類,所以我要生成3個下拉菜單爲Location

  • 國家
  • 國家

我可以做手工像

@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,當我發佈到某個操作時,我需要使用bidden值來獲取對象。

public ActionResult(Location loc) 
{ 
    var x = String.Format("{0}, {1} - {2}", loc.City, loc.Country, loc.State); 
} 

我怎樣才能讓這個助手創建3下拉菜單綁定值當我發佈?

+0

我沒有時間去*如何*現在就這樣做,但它可能是值得創建一個自定義編輯器接受一個複雜的「位置」值包含三個字符串,然後使用UIHint屬性,你仍然可以使用「EditorFor(...)」,但編輯器將使用UIHint的編輯器而不是默認編輯器。或者,您可以將編輯器視圖命名爲複雜的位置模型。 – 2011-05-05 23:47:29

回答

0

繼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) 

,並有在我的網站默認的地方選擇。

1

剛剛創建自己的拓客的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類創建EditorTemplate。只需谷歌爲asp.net mvc editortemplate。 http://www.codecapers.com/post/Display-and-Editor-Templates-in-ASPNET-MVC-2.aspx

就我個人而言,我會堅持EditorTemplates,因爲你可以改變視圖,而不需要重新編譯通常。

+2

'//檢查表達式並生成html'這實際上是我的問題。 – BrunoLM 2011-05-05 20:08:29

+0

添加了關於使用表達式代替反射的博客文章的鏈接。這是你需要做的。 – Andy 2011-05-05 20:23:19