簡體   English   中英

我怎樣才能讓這個 ASP.NET MVC SelectList 工作?

[英]How can I get this ASP.NET MVC SelectList to work?

我在控制器中創建了一個 selectList,以顯示在視圖中。

我正在嘗試動態創建它,有點像這樣......

myViewData.PageOptionsDropDown = 
   new SelectList(new [] {"10", "15", "25", "50", "100", "1000"}, "15");

它編譯,但輸出很糟糕......

<select id="PageOptionsDropDown" name="PageOptionsDropDown">
    <option>10</option>
    <option>15</option>
    <option>25</option>
    <option>50</option>
    <option>100</option>
    <option>1000</option>
</select>

注意沒有項目被選中?

我怎樣才能解決這個問題??

這就是我的做法

IList<Customer> customers = repository.GetAll<Customer>();
IEnumerable<SelectListItem> selectList = 
    from c in customers
    select new SelectListItem
    {
        Selected = (c.CustomerID == invoice.CustomerID),
        Text = c.Name,
        Value = c.CustomerID.ToString()
    };

乍一看,我不確定我知道你在追求什么......

我使用擴展方法:

用法

var departmentItems = departments.ToSelectList(d => d.Code + 
                                               " - " + d.Description,
                                               d => d.Id.ToString(),
                                               " - ");

var functionItems = customerFunctions.ToSelectList(f => f.Description, 
                                                   f => f.Id.ToString(), 
                                                   " - ");

public static class MCVExtentions
{
    public static List<SelectListItem> ToSelectList<T>(
        this IEnumerable<T> enumerable, 
        Func<T, string> text, 
        Func<T, string> value, 
        string defaultOption)
    {
        var items = enumerable.Select(f => new SelectListItem()
                                     {
                                         Text = text(f), 
                                         Value = value(f) 
                                     }).ToList();
        items.Insert(0, new SelectListItem()
                    {
                        Text = defaultOption, 
                        Value = "-1" 
                    });
        return items;
    }
}

使用接受items, dataValueField, dataTextField, selectedValue作為參數的構造函數:

ViewData["myList"] = 
                new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }
                .Select(x => new {value = x, text = x}), 
                "value", "text", "15");

那么在你看來:

<%=Html.DropDownList("myList") %>

基於 Thomas Stock 的回答,我創建了這些重載的ToSelectList方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

public static partial class Helpers
{
    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, bool selectAll = false)
    {
        return enumerable.ToSelectList(value, value, selectAll);
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, object selectedValue)
    {
        return enumerable.ToSelectList(value, value, new List<object>() { selectedValue });
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, IEnumerable<object> selectedValues)
    {
        return enumerable.ToSelectList(value, value, selectedValues);
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, bool selectAll = false)
    {
        foreach (var f in enumerable.Where(x => x != null))
        {
            yield return new SelectListItem()
            {
                Value = value(f).ToString(),
                Text = text(f).ToString(),
                Selected = selectAll
            };
        }
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, object selectedValue)
    {
        return enumerable.ToSelectList(value, text, new List<object>() { selectedValue });
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, IEnumerable<object> selectedValues)
    {
        var sel = selectedValues != null
            ? selectedValues.Where(x => x != null).ToList().ConvertAll<string>(x => x.ToString())
            : new List<string>();

        foreach (var f in enumerable.Where(x => x != null))
        {
            yield return new SelectListItem()
            {
                Value = value(f).ToString(),
                Text = text(f).ToString(),
                Selected = sel.Contains(value(f).ToString())
            };
        }
    }
}

在您的控制器中,您可以執行以下操作:

var pageOptions = new[] { "10", "15", "25", "50", "100", "1000" };
ViewBag.PageOptions = pageOptions.ToSelectList(o => o, "15" /*selectedValue*/);

最后在您的視圖中,輸入:

@Html.DropDownList("PageOptionsDropDown", ViewBag.PageOptions as IEnumerable<SelectListItem>, "(Select one)")

它將產生所需的輸出——當然,如果您不想要第一個空項目,您可以省略上面的"(Select one)"選項標簽:

<select id="PageOptionsDropDown" name="PageOptionsDropDown">
<option value="">(Select one)</option>
<option value="10">10</option>
<option selected="selected" value="15">15</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="1000">1000</option>
</select>

更新:可以在此處找到帶有 XML 注釋的修訂代碼清單。

問題是, SelectList 按設計工作。 錯誤在於設計。 您可以在 SelectedItem 中設置 Selected 屬性,但是如果您使用 GetEnumerator() 遍歷列表(或者如果 Mvc 為您執行此操作),這將完全被忽略。 Mvc 將創建新的 SelectListItems。

您必須將 SelectList ctor 與 SelectListItem[]、Text-Name、Value-Name 和 SelectedValue 一起使用。 請注意將要被選擇的 SelectListItem 的 VALUE 作為 SelectedValue 傳遞,而不是 SelectListItem 本身! 例子:

SelectList sl = new SelectList( new[]{
  new SelectListItem{ Text="one", Value="1"},
  new SelectListItem{ Text="two", Value="2"},
  new SelectListItem{ Text="three", Value="3"}
}, "Text", "Value", "2" );

(沒有測試過,但我遇到了同樣的問題)

那么第二個選項將獲得 selected="selected" 屬性。 看起來不錯的舊數據集;-)

這是一個選項:

myViewData.PageOptionsDropDown = new[] 
{
 new SelectListItem { Text = "10", Value = "10" },
 new SelectListItem { Text = "15", Value = "15", Selected = true }
 new SelectListItem { Text = "25", Value = "25" },
 new SelectListItem { Text = "50", Value = "50" },
 new SelectListItem { Text = "100", Value = "100" },
 new SelectListItem { Text = "1000", Value = "1000" },
}

如果這就是您想要做的所有事情,那么只需將數組聲明為字符串即可修復所選項目問題:

myViewData.PageOptionsDropDown = 
   new SelectList(new string[] {"10", "15", "25", "50", "100", "1000"}, "15");

讓 SelectList 和 SelectedValue 一起工作非常簡單,即使您的屬性不是像 Int、String 或 Double 值這樣的簡單對象。

例子:

假設我們的 Region 對象是這樣的:

public class Region {
     public Guid ID { get; set; }
     public Guid Name { get; set; }
}

你的視圖模型是這樣的:

public class ContactViewModel {
     public DateTime Date { get; set; }
     public Region Region { get; set; }
     public List<Region> Regions { get; set; }
}

您可以使用以下代碼:

@Html.DropDownListFor(x => x.Region, new SelectList(Model.Regions, "ID", "Name")) 

僅當您將 Region 對象的 ToString 方法覆蓋為以下內容時:

public class Region {
     public Guid ID { get; set; }
     public Guid Name { get; set; }

     public override string ToString()
     {
         return ID.ToString();
     }
}

這有 100% 保證工作。

但我真的相信在所有情況下讓 SelectList 100% 工作的最佳方法是使用 Equals 方法針對項目集合中的每個項目測試 DropDownList 或 ListBox 屬性值。

似乎如果您有一個強類型視圖,您需要更改下拉列表的 ID,以便它不是繼承類上的屬性名稱。 然后,您需要在您的編輯 (POST) 方法中放入一些邏輯,以從 FORMCollection 中提取選定的值,並將其放在您的實例中,然后再提交您的更改。

這當然有點奇怪,但我試過了,它有效。

因此,如果您的班級有一個名為 CountryId 的字段,並且您正在顯示一個國家/地區名稱列表,請使下拉列表的 ID 為 CountryName 而不是 CountryId,然后在帖子中,您可以使用 Collection["CountryName"] 做一些事情.

我有同樣的問題。 解決方法很簡單。 只需將傳遞給 DropDownList 助手的“名稱”參數更改為與您的 ViewModel 中現有的任何屬性都不匹配的內容。 在此處閱讀更多信息: http : //www.dotnetguy.co.uk/post/2009/06/25/net-mvc-selectlists-selected-value-does-not-get-set-in-the-view

我引用丹·沃森的話:

在 MVC 中,如果視圖是強類型的,selectlist 的 selected 選項將被覆蓋,並且在構造函數上設置的 selected option 屬性將永遠不會到達視圖,而是選擇下拉列表中的第一個選項(為什么仍然有點神秘) .

干杯!

所有這些答案看起來都不錯,但似乎控制器正在以眾所周知的結構化格式為視圖准備數據,而不是讓視圖簡單地迭代通過模型傳遞的 IEnumerable<> 並構建標准選擇列表,然后讓 DefaultModelBinder通過操作參數將所選項目返回給您。 是的,不,為什么不呢? 關注點分離,是嗎? 讓控制器構建特定於 UI 和視圖的東西似乎很奇怪。

簡單的:

string[] someName = new string[] {"10", "15", "25", "50", "100", "1000"};
myViewData.PageOptionsDropDown = new SelectList(someName, "15");

我就是這樣運行的,沒有任何問題,

public class myViewDataObj
    {
        public SelectList PageOptionsDropDown { get; set; }
    }

public ActionResult About()
        {
            myViewDataObj myViewData = new myViewDataObj();
            myViewData.PageOptionsDropDown =
                  new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }, "15");

            ViewData["myList"] = myViewData.PageOptionsDropDown;
            return View();
        }

<%=Html.DropDownList("myList") %>

如果你這樣做,它也有效,

public ActionResult About()
        {
            myViewDataObj myViewData = new myViewDataObj();
            myViewData.PageOptionsDropDown =
                  new SelectList(new[] { "10", "15", "25", "50", "100", "1000" });

            ViewData["myListValues"] = myViewData.PageOptionsDropDown;
            ViewData["myList"] = "15";
            return View();
        }

<%=Html.DropDownList("myList",(IEnumerable<SelectListItem>)ViewData["myListValues"]) %>

使用你的例子這對我有用:

控制器:

ViewData["PageOptionsDropDown"] = new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }, "15");

看法:

<%= Html.DropDownList("PageOptionsDropDown")%>
MonthRepository monthRepository = new MonthRepository();
IQueryable<MonthEntity> entities = monthRepository.GetAllMonth();
List<MonthEntity> monthEntities = new List<MonthEntity>();

foreach(var r in entities)
{
    monthEntities.Add(r);
}

ViewData["Month"] = new SelectList(monthEntities, "MonthID", "Month", "Mars");

如果您想將一些隨機文本傳遞給 DropDownList,例如--Select--您可以使用以下代碼輕松完成此操作:

@Html.DropDownListFor(x => x.CategoryId, new SelectList(Model.Categories, "Id", "Name"), "--Select--", new { @class = "form-control" })

我這樣做:

List<SelectListItem> list = new List<SelectListItem>{
new SelectListItem {Selected = true, Text = "Select", Value = "0"},
new SelectListItem {Selected = true, Text = "1", Value = "1"},
new SelectListItem {Selected = true, Text = "2", Value = "2"}
};
return list.ToArray();

ToArray() 負責處理這些問題。

模型中選擇的值代替了默認項。 (我同意我沒有閱讀所有帖子)

我不記得 mvc 1 是如何設置的,但它似乎希望選擇列表與其所屬的字段名稱相同......

我發現,正如上面所說的那樣,當它們發送的 ViewData 與字段名稱相同時,我的選擇列表在 mvc2 中不起作用。

例如:

<%= Html.DropDownListFor((model => model.ForID), (SelectList)ViewData["ForName"]) %>

什么時候工作

<%= Html.DropDownListFor((model => model.ForID), (SelectList)ViewData["ForID"]) %>

不起作用,因為 ViewData 名稱“ForID”與它正在工作的字段的名稱相同

一種可能的解釋是您綁定到的選擇列表值不是字符串。

那么在那個例子中,參數 'PageOptionsDropDown' 在你的模型中是一個字符串嗎? 因為如果不是,則不會顯示列表中的選定值。

如果您在 Html.DropDownList 擴展方法中查看 MVC 2 的源代碼,它從不檢查 SelectList 類 SelectedValue 屬性。 它只會嘗試與您的模型匹配。

以上所有都是主題的變體,即如何將一堆數據發送到視圖以獲取下拉列表&它們都一樣好(或多或少)。

問題出在視圖上。 創建您自己的 DropDownList 擴展方法,該方法確實尊重您設置的選擇值,或者手動迭代。 哪個最適合你。

如果您的模型中有一個集合並且您的 View 是強類型的,則此方法的一些變體將起作用:

@Html.DropDownListFor(x => x.RegionID, 
    new SelectList(Model.Regions,"RegionID", "RegionName", Model.RegionID))

-要么-

@Html.DropDownList("RegionID", 
    new SelectList(Model.Regions, "RegionID", "RegionName", Model.RegionID))

可能是您的 ViewData 中存在一些歧義:

看看這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM