Asp.net mvc ASP.NET MVC Html.DropDownList SelectedValue

Asp.net mvc ASP.NET MVC Html.DropDownList SelectedValue,asp.net-mvc,Asp.net Mvc,我尝试过这是RC1,然后升级到RC2,但没有解决问题 // in my controller ViewData["UserId"] = new SelectList( users, "UserId", "DisplayName", selectedUserId.Value); // this has a value 结果:在对象上设置SelectedValue属性 // in my view <%=Html.DropDownList("UserId"

我尝试过这是RC1,然后升级到RC2,但没有解决问题

// in my controller
ViewData["UserId"] = new SelectList(
    users, 
    "UserId", 
    "DisplayName", 
    selectedUserId.Value); // this has a value
结果:在对象上设置SelectedValue属性

// in my view
<%=Html.DropDownList("UserId", (SelectList)ViewData["UserId"])%>
//在我看来
结果:所有预期选项都呈现给客户端,但未设置选定属性。SelectedValue中的项目存在于列表中,但列表中的第一个项目始终默认为selected

我应该怎么做

更新 多亏了约翰·费米内拉的回答,我才发现了问题所在。“UserId”是我的视图强类型化到的模型中的一个属性。当Html.DropDownList(“UserId”更改为除“UserId”之外的任何其他名称时,所选值将正确呈现

但这会导致值未绑定到模型。

请尝试以下操作:

public class Person {
    public int Id { get; set; }
    public string Name { get; set; }
}
然后:

var list = new[] {   
    new Person { Id = 1, Name = "Name1" }, 
    new Person { Id = 2, Name = "Name2" }, 
    new Person { Id = 3, Name = "Name3" } 
};

var selectList = new SelectList(list, "Id", "Name", 2);
ViewData["People"] = selectList;

Html.DropDownList("PeopleClass", (SelectList)ViewData["People"])
通过MVC RC2,我得到:

<select id="PeopleClass" name="PeopleClass">
    <option value="1">Name1</option>
    <option selected="selected" value="2">Name2</option>
    <option value="3">Name3</option>
</select>

名称1
姓名2
名字3

这似乎是SelectExtensions类中的一个错误,因为它只会检查所选项目的ViewData而不是模型。因此,诀窍是将所选项目从模型复制到属性名称下的ViewData集合中

这是我在MVC论坛上给出的答案,我也有一个更完整的答案,使用

给出一个模型

public class ArticleType
{
   public Guid Id { get; set; }
   public string Description { get; set; }
}

public class Article
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public ArticleType { get; set; }
}
和一个基本的视图模型

public class ArticleModel
{
     public Guid Id { get; set; }
     public string Name { get; set; }

     [UIHint("DropDownList")]
     public Guid ArticleType { get; set; }
}
然后我们编写一个DropDownList编辑器模板,如下所示

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<script runat="server">  
    IEnumerable<SelectListItem> GetSelectList()
    {
        var metaData = ViewData.ModelMetadata;
        if (metaData == null)
        {
            return null;
        }

        var selected = Model is SelectListItem ? ((SelectListItem) Model).Value : Model.ToString();
        ViewData[metaData.PropertyName] = selected;

        var key = metaData.PropertyName + "List";
        return (IEnumerable<SelectListItem>)ViewData[key];
    }
</script>
<%= Html.DropDownList(null, GetSelectList()) %>

IEnumerable GetSelectList()
{
var metaData=ViewData.ModelMetadata;
if(元数据==null)
{
返回null;
}
var selected=模型是SelectListItem?((SelectListItem)模型)。值:Model.ToString();
ViewData[metaData.PropertyName]=已选择;
var key=metaData.PropertyName+“列表”;
返回(IEnumerable)视图数据[键];
}
如果您将视图模型中的ArticleType更改为SelectListItem,这也会起作用,尽管您必须按照Kazi的博客实现一个类型转换器并注册它,以强制绑定器将其视为简单类型

在你的控制器中,我们有

public ArticleController 
{
     ...
     public ActionResult Edit(int id)
     {
          var entity = repository.FindOne<Article>(id);
          var model = builder.Convert<ArticleModel>(entity);

          var types = repository.FindAll<ArticleTypes>();
          ViewData["ArticleTypeList"] = builder.Convert<SelectListItem>(types);

          return VIew(model);
     }
     ...
}
公共控制器
{
...
公共操作结果编辑(int id)
{
var entity=repository.FindOne(id);
var model=builder.Convert(实体);
var types=repository.FindAll();
ViewData[“ArticleTypeList”]=builder.Convert(类型);
返回视图(模型);
}
...
}

我就是这样解决这个问题的:

我有以下几点:

控制器:

ViewData["DealerTypes"] = Helper.SetSelectedValue(listOfValues, selectedValue) ;
看法


更改如下:

看法



看起来,下拉框的名称不能与ViewData的名称相同,但它工作起来很奇怪。

问题在于,下拉框的工作方式与列表框不同,至少与ASP.NET MVC2设计所期望的方式不同:下拉框只允许零或一个值,因为列表框可以有多个值选择。因此,严格使用HTML时value不应该作为“selected”标志出现在选项列表中,而应该出现在输入本身中

请参见以下示例:

<select id="combo" name="combo" value="id2">
  <option value="id1">This is option 1</option>
  <option value="id2" selected="selected">This is option 2</option>
  <option value="id3">This is option 3</option>
</select>

<select id="listbox" name="listbox" multiple>
  <option value="id1">This is option 1</option>
  <option value="id2" selected="selected">This is option 2</option>
  <option value="id3">This is option 3</option>
</select>

这是选项1
这是选项2
这是选项3
这是选项1
这是选项2
这是选项3
组合框选择了选项,但也设置了其值属性。因此,如果希望ASP.NET MVC2呈现dropbox并选择特定值(即默认值等),则应在呈现时为其指定一个值,如下所示:

// in my view             
<%=Html.DropDownList("UserId", selectListItems /* (SelectList)ViewData["UserId"]*/, new { @Value = selectedUser.Id } /* Your selected value as an additional HTML attribute */)%>
//在我看来

在ASP.NET MVC 3中,您只需将列表添加到ViewData

var options = new List<SelectListItem>();

options.Add(new SelectListItem { Value = "1", Text = "1" });
options.Add(new SelectListItem { Value = "2", Text = "2" });
options.Add(new SelectListItem { Value = "3", Text = "3", Selected = true });

ViewData["options"] = options;
您不必在DropDownList调用中手动“使用”列表。这样做也可以为我正确设置所选值

免责声明:

  • 还没有在web窗体视图引擎中尝试过这一点,但它也应该可以工作
  • 我还没有在v1和v2中测试过这个,但它可能会工作

  • 上一篇MVC 3文章中的代码不起作用,但这是一个很好的开始。我会修复它。我已经测试了这段代码,它在MVC 3 Razor C中工作。这段代码使用ViewModel模式填充返回
    列表的属性

    模范班

    public class Product
    {
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
    
    using System.Web.Mvc;
    
    public class ProductListviewModel
    {
        public List<SelectListItem> Products { get; set; }
    }
    
    ViewModel类

    public class Product
    {
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
    
    using System.Web.Mvc;
    
    public class ProductListviewModel
    {
        public List<SelectListItem> Products { get; set; }
    }
    
    HTML输出类似于

    <select id="Products" name="Products">
        <option value="3">Product: Widget 10.00</option>
        <option value="4">Product: Gadget 5.95</option>
    </select>
    
    
    产品:Widget 10.00
    产品:Gadget 5.95
    

    取决于您如何格式化输出。我希望这会有所帮助。代码确实有效。

    您仍然可以将下拉列表命名为“UserId”,并且模型绑定仍然可以正常工作

    此操作的唯一要求是,包含SelectList的ViewData键与要绑定的模型属性的名称不同。在您的特定情况下,这可能是:

    // in my controller
    ViewData["Users"] = new SelectList(
        users, 
        "UserId", 
        "DisplayName", 
        selectedUserId.Value); // this has a value
    
    // in my view
    <%=Html.DropDownList("UserId", (SelectList)ViewData["Users"])%>
    
    //在我的控制器中
    ViewData[“用户”]=新建选择列表(
    用户,
    “用户ID”,
    “显示名称”,
    selectedUserId.Value);//这有一个值
    //在我看来
    
    这将生成一个名为UserId的select元素,该元素与模型中的UserId属性具有相同的名称,因此模型绑定器将使用html.DropDownList帮助程序生成的html的select元素中选择的值对其进行设置

    我不知道为什么当您在ViewData中使用与属性名相等的键放置选择列表时,特定的Html.DropDownList构造函数不会选择SelectList中指定的值。我怀疑这与DropDownList帮助器在其他场景中的使用方式有关,在其他场景中,惯例是您有一个SelectList在ViewData中使用与模型中的属性相同的名称。这将正常工作:

    // in my controller
    ViewData["UserId"] = new SelectList(
        users, 
        "UserId", 
        "DisplayName", 
        selectedUserId.Value); // this has a value
    
    // in my view
    <%=Html.DropDownList("UserId")%>
    
    //在我的控制器中
    ViewData[“UserId”]=新建选择列表(
    用户,
    “用户ID”,
    “显示名称”,
    selectedUserId.Value);//这有一个值
    //在我看来
    
    如果我们不认为这是团队应该修复的错误,至少MSDN应该改进文档。令人困惑的真正原因是这篇糟糕的文档。在本文中,它解释了参数<
    <select id="Products" name="Products">
        <option value="3">Product: Widget 10.00</option>
        <option value="4">Product: Gadget 5.95</option>
    </select>
    
    // in my controller
    ViewData["Users"] = new SelectList(
        users, 
        "UserId", 
        "DisplayName", 
        selectedUserId.Value); // this has a value
    
    // in my view
    <%=Html.DropDownList("UserId", (SelectList)ViewData["Users"])%>
    
    // in my controller
    ViewData["UserId"] = new SelectList(
        users, 
        "UserId", 
        "DisplayName", 
        selectedUserId.Value); // this has a value
    
    // in my view
    <%=Html.DropDownList("UserId")%>
    
    Type: System.String
    The name of the form field to return.
    
    public class Person {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
    public class PersonsSelectViewModel{
        public string SelectedPersonId,
        public List<SelectListItem> Persons;
    }
    
    private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata,
                string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple,
                IDictionary<string, object> htmlAttributes)
    {
        ...
    
        bool usedViewData = false;
    
        // If we got a null selectList, try to use ViewData to get the list of items.
        if (selectList == null)
        {
            selectList = htmlHelper.GetSelectData(name);
            usedViewData = true;
        }
    
        object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(fullName, typeof(string[])) : htmlHelper.GetModelStateValue(fullName, typeof(string));
    
        // If we haven't already used ViewData to get the entire list of items then we need to
        // use the ViewData-supplied value before using the parameter-supplied value.
        if (defaultValue == null && !String.IsNullOrEmpty(name))
        {
            if (!usedViewData)
            {
                defaultValue = htmlHelper.ViewData.Eval(name);
            }
            else if (metadata != null)
            {
                defaultValue = metadata.Model;
            }
        }
    
        if (defaultValue != null)
        {
            selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
        }
    
        ...
    
        return tagBuilder.ToMvcHtmlString(TagRenderMode.Normal);
    }
    
    if ((defaultValue != null) && (!selectList.Any(i=>i.Selected)))
    {
        selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
    }
    
    @Html.DropDownList("Example", new SelectList(Model.FeeStructures, "Id", "NameOfFeeStructure", Model.Matters.FeeStructures))