Làm thế nào tôi có thể làm cho ASP.NET MVC SelectList này hoạt động?


126

Tôi tạo một selectList trong bộ điều khiển của mình, để hiển thị trong khung nhìn.

Tôi đang cố gắng tạo ra nó một cách nhanh chóng, điều tương tự .. như thế này ...

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

Nó biên dịch, nhưng đầu ra rất tệ ...

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

Chú ý không có mục nào được chọn?

Làm thế nào tôi có thể sửa lỗi này??


1
Sáu câu trả lời ... được yêu thích ... không có ý kiến ​​gì: / Tôi sẽ cho nó +1
vào

Câu trả lời:


128

Đây là cách tôi làm

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

Ở cái nhìn thứ hai tôi không chắc tôi biết bạn là gì sau ...


2
Cảm ơn bạn điều này đã giúp tôi tìm ra công cụ này.
Cadoo

6
Không khắc phục sự cố mục đã chọn nhưng đó là một cách tuyệt vời để tránh các chuỗi ma thuật cho danh sách được chọn! Chúc mừng
Alan Christensen

11
Để khắc phục sự cố mục đã chọn, hãy thêm mã sau đây: khách hàng được chọn hiện tại SelectList sList = new SelectList(selectList, "Text", "Value", selected);ở đâuselected
jao

68

Tôi sử dụng một phương pháp mở rộng:

sử dụng

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

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

với

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

đẹp. Tôi đã thêm một Func đã chọn, tùy chọn defaultValue và quá tải thứ hai mà không có bất kỳ mặc định nào để chỉ định và điều này hoạt động một điều trị. Nhân tiện, nếu bạn muốn tạo kiểu trả về IEnumerable <SelectListItem>, bạn có thể sử dụng cú pháp trả về lợi tức để làm cho giao diện này thực sự sạch sẽ
Chris Meek

48

Sử dụng hàm tạo chấp nhận items, dataValueField, dataTextField, selectedValuelàm tham số:

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

Sau đó, theo quan điểm của bạn:

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

3
anh chàng tốt bụng :) tôi thích! tôi đã cố gắng để làm điều này .. nhưng tôi không thể có được phần .Select (..) .. tốt đẹp :) Tôi sẽ thử ở nhà, sau đó :)
Pure.Krom

1
Heya Cagdas. hoạt động tuyệt vời, ngoại trừ trường đã chọn không được chọn. bất kỳ ý tưởng? Đây có phải là một lỗi trong công cụ MVC?
Pure.Krom

2
Mục đã chọn hoạt động khi bạn thêm mục Chọn danh sách vào đối tượng ViewData (như trong ViewData ["myList"] = new SelectList ..) và sau đó kết xuất nó với <% = Html.DropDownList ("myList")%>. Tôi không thể có được mục đã chọn để làm việc mà không làm theo cách này mặc dù. Kỳ dị.
Tekağdaş Tekin

@Cagdas - hi một lần nữa anh chàng .. tôi vẫn chưa tìm ra này :( Gì đây về một ViewData ??? Tôi có một ViewData gõ mạnh với đó là tài sản riêng .... ???
Pure.Krome

@ Pure.Krom - Tôi lấy thuộc tính đó từ ví dụ của bạn trong câu hỏi. Bây giờ tôi đang chỉnh sửa mẫu mã. Xin vui lòng xem chỉnh sửa của tôi trong một vài giây.
Tekağdaş Tekin

19

Dựa trên câu trả lời của Thomas Stock, tôi đã tạo ra các ToSelectListphương thức quá tải này :

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

Trong bộ điều khiển của bạn, bạn có thể làm như sau:

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

Và cuối cùng trong Chế độ xem của bạn, đặt:

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

Nó sẽ dẫn đến kết quả đầu ra mong muốn - tất nhiên, bạn có thể bỏ "(Select one)"tùy chọn Nhãn ở trên nếu bạn không muốn mục trống đầu tiên:

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

Cập nhật: Một danh sách mã sửa đổi có thể được tìm thấy ở đây với các bình luận XML.


13

Vấn đề là, SelectList hoạt động như thiết kế. Các lỗi là trong thiết kế. Bạn có thể đặt Thuộc tính được chọn trong ChọnItem, nhưng điều này sẽ hoàn toàn bị bỏ qua, nếu bạn duyệt qua danh sách với GetEnumerator () (hoặc nếu Mvc làm điều đó cho bạn). Mvc sẽ tạo ra SelectListItems mới thay thế.

Bạn phải sử dụng ctor SelectList với SelectListItem [], Text-Name, Value-Name và chọnValue. Hãy lưu ý để vượt qua với tư cách là Chọn giá trị GIÁ TRỊ của SelectListItem, mà bạn muốn được chọn, chứ không phải là chính ListListItem! Thí dụ:

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

(không thử nghiệm điều này, nhưng tôi đã có cùng một vấn đề)

sau đó tùy chọn thứ 2 sẽ nhận được thuộc tính được chọn = "đã chọn". Trông giống như DataSets cũ ;-)


11

Đây là một lựa chọn:

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" },
}

new SelectListItem {Được chọn = true, Text = "15", Value = "15"} cho giá trị được chọn.
Cadoo

Rất tiếc, ừ, quên bao gồm tài sản 'Đã chọn', cảm ơn Cadoo =)
murki

10

Nếu đó thực sự là tất cả những gì bạn muốn làm thì chỉ cần khai báo mảng là chuỗi khắc phục sự cố mục đã chọn:

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

7

Rất đơn giản để làm cho SelectList và chọnValue hoạt động cùng nhau, ngay cả khi thuộc tính của bạn không phải là một đối tượng đơn giản như giá trị Int, String hoặc Double.

Thí dụ:

Giả sử đối tượng Vùng của chúng ta giống như thế này:

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

Và mô hình xem của bạn là một cái gì đó như:

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

Bạn có thể có mã dưới đây:

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

Chỉ khi bạn ghi đè phương thức ToString của đối tượng Vùng thành một cái gì đó như:

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

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

Điều này có 100% garantee để làm việc.

Nhưng tôi thực sự tin rằng cách tốt nhất để làm cho SelectList hoạt động 100% trong tất cả các khoảng thời gian là bằng cách sử dụng phương thức Equals để kiểm tra giá trị thuộc tính DropDownList hoặc ListBox đối với từng mục trên bộ sưu tập vật phẩm.


5

Có vẻ như nếu bạn có chế độ xem được gõ mạnh, bạn cần thay đổi ID của danh sách thả xuống để nó KHÔNG phải là tên của một tài sản trong lớp được nhập. Sau đó, bạn cần đặt một số logic trong phương thức chỉnh sửa (POST) của mình để lấy ra giá trị đã chọn từ FORMCollection và đưa nó vào ví dụ của bạn trước khi thực hiện các thay đổi của bạn.

Điều này chắc chắn là hơi lạ, nhưng tôi đã thử nó và nó hoạt động.

Vì vậy, nếu lớp của bạn có một trường có tên là CountryId và bạn đang hiển thị danh sách tên quốc gia, hãy thả xuống có id của CountryName thay vì CountryId, thì trong bài đăng, bạn có thể làm gì đó với Bộ sưu tập ["CountryName"] .


1
Vâng, tôi đã có vấn đề tương tự. Đơn giản chỉ cần thay đổi tên làm việc. Cảm ơn!
davekaro

4

Tôi cũng có chính xác vấn đề đấy. Giải pháp rất đơn giản. Chỉ cần thay đổi tham số "name" được truyền cho trình trợ giúp DropDownList thành một cái gì đó không khớp với bất kỳ thuộc tính nào có trong ViewModel của bạn. đọc thêm tại đây: http://www.dotnetguy.co.uk/post/2009/06/25/net-mvc-selectlists-selected-value-does-not-get-set-in-the-view

Tôi trích dẫn Dan Watson:

Trong MVC nếu chế độ xem được gõ mạnh, tùy chọn đã chọn của danh sách chọn sẽ bị ghi đè và thuộc tính tùy chọn đã chọn được đặt trên hàm tạo sẽ không bao giờ đạt đến chế độ xem và tùy chọn đầu tiên trong danh sách thả xuống sẽ được chọn thay thế (tại sao vẫn còn một chút bí ẩn) .

chúc mừng


3

Tất cả các câu trả lời này trông rất tuyệt, nhưng dường như bộ điều khiển đang chuẩn bị dữ liệu cho Chế độ xem theo định dạng có cấu trúc nổi tiếng so với việc để chế độ xem đơn giản lặp lại một IEnumerable <> được gửi qua mô hình và xây dựng danh sách chọn tiêu chuẩn sau đó cho DefaultModelBinder cung cấp các mục đã chọn trở lại cho bạn thông qua một tham số hành động. Có, không, tại sao không? Tách biệt mối quan tâm, có? Có vẻ kỳ quặc khi có bộ điều khiển để xây dựng một cái gì đó để UI và View cụ thể.


3

Đơn giản:

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

2

Tôi chỉ chạy nó như thế này và không có vấn đề gì,

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") %>

nó cũng hoạt động nếu bạn làm điều này,

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"]) %>

1

Sử dụng ví dụ của bạn, điều này làm việc cho tôi:

bộ điều khiển:

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

lượt xem:

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

Vâng, điều đó cũng làm việc cho tôi. Trong trường hợp của tôi, danh sách là một đối tượng Mô hình thực thể. Trình điều khiển: ViewData ["Thể loại"] = new SelectList (db.C Chuyên.ToList (), "CategoryId", "CategoryName", "15"); Xem: Html.DropDownList ("CategoryId", (Chọn danh sách) ViewData ["Thể loại"], "--select--")
Junior Mayhé

1
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");

1

Tôi làm như thế này:

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 () chăm sóc các vấn đề.


1

Nếu bạn muốn vượt qua một số văn bản ngẫu nhiên để DropDownList của bạn, ví dụ --Chọn-- bạn dễ dàng có thể làm điều này sử dụng mã này:

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

0

Đây có thể là trường hợp bạn có một chút mơ hồ trong ViewData của mình:

Hãy xem đây


0

giá trị được chọn trong mô hình sẽ tận dụng thay vì mục mặc định. (Tôi đồng ý tôi đã không đọc tất cả các bài viết)


0

Tôi không thể nhớ mvc 1 đã được thiết lập như thế nào, nhưng có vẻ như nó muốn danh sách chọn có tên giống với trường mà nó thuộc về ...

Những gì tôi tìm thấy, như một người nào đó đã nói ở trên, là các danh sách lựa chọn của tôi không hoạt động trong mvc2 khi ViewData mà chúng được gửi như được đặt tên giống như trường.

Ví dụ:

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

hoạt động khi

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

không hoạt động vì tên ViewData "ForID" được đặt tên giống như trường mà nó đang hoạt động


0

Một lời giải thích có thể là giá trị danh sách lựa chọn mà bạn đang ràng buộc không phải là một chuỗi.

Vì vậy, trong ví dụ đó, tham số 'PageOptionsDropDown' có phải là một chuỗi trong mô hình của bạn không? Bởi vì nếu không thì giá trị được chọn trong danh sách sẽ không được hiển thị.


0

Nếu bạn tìm mã nguồn cho MVC 2 tại phương thức mở rộng Html.DropDownList, thì nó không bao giờ kiểm tra thuộc tính lớp ChọnListValue. Nó sẽ chỉ cố gắng để phù hợp với mô hình của bạn.

Tất cả các mục trên đều là các biến thể của một chủ đề, tức là làm thế nào để bạn gửi một loạt dữ liệu tới chế độ xem cho danh sách thả xuống & tất cả đều tốt như nhau (ít nhiều).

Vấn đề là trong quan điểm. Tạo phương thức tiện ích mở rộng DropDownList của riêng bạn, tôn trọng giá trị chọn mà bạn đặt hoặc lặp lại bằng tay. Mà bao giờ làm việc tốt nhất cho bạn.


@Franz Antesberger nói nhiều điều tương tự.
Simon Halsey

0

Nếu bạn có một bộ sưu tập trong mô hình của mình và Chế độ xem của bạn rất mạnh, một số biến thể của điều này sẽ hoạt động:

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

-hoặc là-

@Html.DropDownList("RegionID", 
    new SelectList(Model.Regions, "RegionID", "RegionName", Model.RegionID))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.