2012-01-05 70 views
0

我想在我的视图中实现编辑地址。MVC中的下拉框3

地址具有街道,城镇等的基本字符串。它还具有国家ID。我在我的国家数据库中有一个表格。

在我控制我创建的SelectList这些国家:

ViewBag.Countries = _countryRepo.GetAll().Select(c => new SelectListItem { Text = c.Name, Value = c.Id }); 

现在,在我看来,我希望能够利用这个选择列表允许用户选择国家。

我本来以为:

@Html.DropDownList("countryId", (IEnumerable<Country>)ViewBag.Countries, "Select") 

我有两个地址:

public class Company() 
{ 
    public Address HeadOffice { get; set; } 
    public Address SecondOffice { get; set; } 
} 

所以显示视图时,我需要有所示的选择国家。我不认为我可以做到这一点在我的控制器,因为如果我选择一个这样的:

ViewBag.Countries = _countryRepo.GetAll().Select(c => new SelectListItem { Text = c.Name, Value = c.Id, Selected = c.Id == model.HeadOffice.Id ? true : false }); 

这只会为HeadOffice上工作。

从我可以有两种选择。有两个不同的选择列表或在视图中手动构建选择列表:

<select name="HeadOffice.CountryId"> 
    @foreach(var c in (IEnumerable<Country>)ViewBag.Countries) 
    { 
     <option value="@c.Id" @(c.Id == Model.HeadOffice.Id ? "selected='true'" : "">@c.Name</option> 
    } 
</select> 

什么是最佳方式?这两个看起来不对,也不好。有没有更好的方法来解决这个问题?

回答

2

我会用一个视图模型,它接受国家名单一次,然后露出2名不同的列表。这样,你只查询数据库的人,但仍让你查看干净

视图模型:

public class MyViewModel 
{ 
    public Address HeadOffice { get; set; } 
    public Address SecondOffice { get; set; } 

    public IEnumerable<Country> Countries { get;set;} 

    public IEnumerable<SelectListItem> HeadOfficeCountries 
    { 
    get 
    { 
     return GetCountriesList(Countries, HeadOffice.Id); 
    } 
    } 

    public IEnumerable<SelectListItem> SecondOfficeCountries 
    { 
    get 
    { 
     return GetCountriesList(Countries, SecondOffice.Id); 
    } 
    } 

    private IEnumerable<SelectListItem> GetCountriesList(IEnumerable<Country> countries, int forAddress) 
    { 
    return countries.Select(c => new SelectListItem { Text = c.Name, Value = c.Id, Selected = c.Id == forAddress ? true : false }); 
    } 
} 
+0

优秀!好主意 - 我会这样做的。谢谢。 – Terry 2012-01-05 20:40:05

+0

@特里伟大!很高兴我能帮上忙。 – 2012-01-05 20:43:34

+0

@BassamMehanni你在这里写了两次相同的代码。 ASP.NET MVC的原则之一是遵循DRY方法。 – tugberk 2012-01-05 20:46:56

1

看一看下面的博客文章:

A Way of Working with Html Select Element (AKA DropDownList) In ASP.NET MVC

你会发现博客文章内的所有细节。

编辑:

对于你的情况,下面的代码应该很好地工作:

public ActionResult Index() { 

    ViewBag.DLForHeadOffice = GetItems(model.HeadOffice.Id); 
    ViewBag.DLForSecondOffice = GetItems(model.SecondOffice.Id); 

    //continue your code 
} 


private IEnumerable<SelectListItem> GetItems(int id) { 

    _countryRepo.GetAll(). 
     Select(c => 
      new SelectListItem { 
       Text = c.Name, 
       Value = c.Id, 
       Selected = c.Id == id ? true : false 
      } 
     );  
} 
+0

博客帖子链接已丢失,但我不认为这是有意的。 – 2012-01-05 20:34:03

+0

@FrazellThomas现在它在那里。 – tugberk 2012-01-05 20:34:47

+0

谢谢,但我已经知道如何使用下拉列表。我的问题是让它适用于两个不同地址的最佳方式。 – Terry 2012-01-05 20:39:42

0

你有没有考虑使用HTML助手?

我在我们的类中有一些处理字典缓存的私有静态字典变量,所以我们不必在每次渲染下拉列表时获取国家列表(这就是countryDictionary的下面)。

public static MvcHtmlString CountrySelectFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string emptyText, object htmlAttributes) 
    { 
     SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = emptyText != null ? emptyText : "", Value = "" } }; 
     return htmlHelper.DropDownListFor(expression, emptyText != null ? SingleEmptyItem.Concat(new SelectList(countryDictionary, "Key", "Value")) : new SelectList(countryDictionary, "Key", "Value"), htmlAttributes); 
    } 

从这里,你注册,你把你的HTML助手在命名空间后,您可以使用:

<%: Html.CountrySelectFor(model => Model.HeadOffice.CountryId) %> 

仅供参考,这里是出于对countryList片段。下面的“Caching”行不会为您存在,这些是我们为管理应用程序缓存而创建的一些自定义类。

private static Dictionary<int, string> countryList 
    { 
     get 
     { 
      IList<Models.Country> countries = Caching.HTTPCache.Get(Caching.Common.CountryCacheName) as IList<Models.Country>; 

      if (countries == null) 
      { 
       countries = Models.Country.Get(); //Loads all countries from the DB 
       Caching.HTTPCache.Add(Caching.Common.CountryCacheName, countries , new TimeSpan(0, 0, Caching.Common.CountryCacheDuration, 0, 0)); //Adds the results to the cache 
      } 

      return countries .ToDictionary(t => t.CountryId, t => t.CountryName); 
     } 
    }