MVC 3中的下拉框

时间:2012-01-05 20:24:01

标签: .net asp.net-mvc-3 razor

我正在尝试在我的视图中实现编辑地址。

地址具有街道,城镇等的基本字符串。它还具有国家/地区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>

最好的方法是什么?两者似乎都错了而且不好看。有没有更好的方法来解决这个问题?

3 个答案:

答案 0 :(得分:2)

我会使用ViewModel接收国家/地区列表,然后公开2个不同的列表。这样您只需查询数据库但仍保持View clean

视图模型:

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 });
  }
}

答案 1 :(得分: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 
            }
        );       
}

答案 2 :(得分:0)

您是否考虑过使用HTML帮助程序?

我的类中有一些私有的静态Dictionary变量,用于处理字典的缓存,因此每次下拉时都不需要获取国家/地区列表(即下面是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 Helper放入其中,您可以使用:

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

仅供参考,这里是countryList的代码片段。下面的“缓存”行不会存在,这些是我们为管理应用程序缓存而制作的一些自定义类。

 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);
        }
    }