ASP.NET Core MVC'de Etiket Yardımcısı'nı seçin


162

ASP.NET Core'da seçim etiketi yardımcısı için yardıma ihtiyacım var.

Seçme etiketi yardımcısına bağlanmaya çalıştığım çalışanların bir listesi var. Çalışanlarım içinde List<Employee> EmployeesListve seçilen bir değer EmployeeIdmülke gidecek . Görünüm modelim şöyle görünüyor:

public class MyViewModel
{
   public int EmployeeId { get; set; }
   public string Comments { get; set; }
   public List<Employee> EmployeesList {get; set; }
}

Çalışan sınıfım şöyle:

public class Employee
{
   public int Id { get; set; }
   public string FullName { get; set; }
}

Benim sorum, seçim etiketi yardımcıma açılır listede Idgörüntülenirken değeri olarak kullanmasını nasıl söyleyebilirim FullName?

<select asp-for="EmployeeId" asp-items="???" />

Bununla ilgili bazı yardımları takdir ediyorum. Teşekkürler.


3
eklemem gerektiğini düşündüğüm bir şey, seçim etiketini hemen kapatırsanız işe yaramaz gibi görünüyor her zaman etiketleri </select> ile kapatın etiket yardımcı <select asp-for ..... /> ile
çalışmadı

Sadece bir ipucu. iskele denetleyicileri genellikle bu tür şeylere en iyi yolları gösterir
Neville Nazerane

Yanıtlar:


379

SELECT öğesi oluşturmak için Etiket Seç yardımcılarını kullanma

GET eyleminizde, görünüm modelinizin bir nesnesini oluşturun, EmployeeListcollection özelliğini yükleyin ve bunu görünüme gönderin.

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.EmployeesList = new List<Employee>
    {
        new Employee { Id = 1, FullName = "Shyju" },
        new Employee { Id = 2, FullName = "Bryan" }
    };
    return View(vm);
}

Oluşturma görünümünüzde, özellikten yeni bir SelectListnesne oluşturun ve bunu EmployeeListözellik için değer olarak asp-itemsiletin.

@model MyViewModel
<form asp-controller="Home" asp-action="Create">

    <select asp-for="EmployeeId" 
            asp-items="@(new SelectList(Model.EmployeesList,"Id","FullName"))">
        <option>Please select one</option>
    </select>

    <input type="submit"/>

</form>

Ve gönderilen form verilerini kabul etmek için HttpPost eylem yönteminiz.

[HttpPost]
public IActionResult Create(MyViewModel model)
{
   //  check model.EmployeeId 
   //  to do : Save and redirect
}

Veya

Görünüm modelinizde List<SelectListItem>açılır öğeleriniz için bir özellik varsa.

public class MyViewModel
{
    public int EmployeeId { get; set; }
    public string Comments { get; set; }
    public List<SelectListItem> Employees { set; get; }
}

Ve harekete geçtiğinizde,

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "1"},
        new SelectListItem {Text = "Sean", Value = "2"}
    };
    return View(vm);
}

Ve görünümde, doğrudan Employeesözelliği için kullanabilirsiniz asp-items.

@model MyViewModel
<form asp-controller="Home" asp-action="Create">

    <label>Comments</label>
    <input type="text" asp-for="Comments"/>

    <label>Lucky Employee</label>
    <select asp-for="EmployeeId" asp-items="@Model.Employees" >
        <option>Please select one</option>
    </select>

    <input type="submit"/>

</form>

Sınıf SelectListItem, Microsoft.AspNet.Mvc.Renderingad alanına aittir .

Select öğesi için açık bir kapatma etiketi kullandığınızdan emin olun. Kendiliğinden kapanan etiket yaklaşımını kullanırsanız, etiket yardımcısı boş bir SELECT öğesi oluşturur!

Aşağıdaki yaklaşım işe yaramayacak

<select asp-for="EmployeeId" asp-items="@Model.Employees" />

Ama bu işe yarayacak.

<select asp-for="EmployeeId" asp-items="@Model.Employees"></select>

Varlık çerçevesini kullanarak veritabanı tablonuzdan veri alma

Yukarıdaki örnekler, seçenekler için sabit kodlanmış öğeler kullanmaktadır. Bu yüzden ben birçok kişi bunu kullanmak gibi Varlık çerçevesini kullanarak veri almak için bazı örnek kod ekleyeceğini düşündüm.

DbContext nesnenizin, varlık sınıfının ve böyle bir özelliğe sahip olduğu Employeestürde bir özelliğe sahip olduğunu varsayalım.DbSet<Employee>EmployeeIdName

public class Employee
{
   public int Id { set; get; }
   public string Name { set; get; }
}

Çalışanları almak için bir LINQ sorgusu kullanabilir ve SelectListItemher çalışan için bir nesne listesi oluşturmak üzere LINQ ifadenizdeki Select yöntemini kullanabilirsiniz .

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = context.Employees
                          .Select(a => new SelectListItem() {  
                              Value = a.Id.ToString(),
                              Text = a.Name
                          })
                          .ToList();
    return View(vm);
}

contextDb bağlam nesneniz olduğunu varsayarsak . Görünüm kodu yukarıdakiyle aynıdır.

SelectList'i kullanma

Bazı insanlar SelectList, seçenekleri oluşturmak için gereken öğeleri tutmak için sınıf kullanmayı tercih eder .

public class MyViewModel
{
    public int EmployeeId { get; set; }
    public SelectList Employees { set; get; }
}

Şimdi GET eyleminizde, görünüm modelinin özelliğini SelectListdoldurmak için yapıcıyı kullanabilirsiniz Employees. dataValueFieldVe dataTextFieldparametrelerini belirttiğinizden emin olun .

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = new SelectList(GetEmployees(),"Id","FirstName");
    return View(vm);
}
public IEnumerable<Employee> GetEmployees()
{
    // hard coded list for demo. 
    // You may replace with real data from database to create Employee objects
    return new List<Employee>
    {
        new Employee { Id = 1, FirstName = "Shyju" },
        new Employee { Id = 2, FirstName = "Bryan" }
    };
}

İşte ben arıyorum GetEmployeesyöntemi, bir ile her Çalışan nesnelerin listesini almak Idve FirstNamemülk ve ben bu özellikleri kullanmak DataValueFieldve DataTextFieldiçinde SelectListyarattığımız nesne. Sabit kodlu listeyi, bir veritabanı tablosundan veri okuyan bir koda değiştirebilirsiniz.

Görünüm kodu aynı olacaktır.

<select asp-for="EmployeeId" asp-items="@Model.Employees" >
    <option>Please select one</option>
</select>

Dizeler listesinden bir SELECT öğesi oluşturun.

Bazen bir dize listesinden bir seçim öğesi oluşturmak isteyebilirsiniz. Bu durumda, SelectListyalnızcaIEnumerable<T>

var vm = new MyViewModel();
var items = new List<string> {"Monday", "Tuesday", "Wednesday"};
vm.Employees = new SelectList(items);
return View(vm);

Görünüm kodu aynı olacaktır.

Seçilen seçenekleri ayarlama

Bazı durumlarda, bir seçeneği SELECT öğesinde varsayılan seçenek olarak ayarlamak isteyebilirsiniz (Örneğin, bir düzenleme ekranında önceden kaydedilmiş seçenek değerini yüklemek istersiniz). Bunu yapmak için, EmployeeIdözellik değerini seçilmesini istediğiniz seçeneğin değerine ayarlayabilirsiniz .

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "11"},
        new SelectListItem {Text = "Tom", Value = "12"},
        new SelectListItem {Text = "Jerry", Value = "13"}
    };
    vm.EmployeeId = 12;  // Here you set the value
    return View(vm);
}

Bu, sayfa oluşturulduğunda seçim öğesindeki Tom seçeneğini seçer.

Çoklu seçim açılır menüsü

Çoklu seçim açılır menüsünü oluşturmak istiyorsanız, görünümünüzde özellik için kullandığınız görünüm modeli özelliğini asp-forbir dizi türüyle değiştirebilirsiniz.

public class MyViewModel
{
    public int[] EmployeeIds { get; set; }
    public List<SelectListItem> Employees { set; get; }
}

Bu multiple, kullanıcının birden çok seçenek seçmesine olanak tanıyan özniteliğe sahip select öğesinin HTML işaretlemesini oluşturur .

@model MyViewModel
<select id="EmployeeIds" multiple="multiple" name="EmployeeIds">
    <option>Please select one</option>
    <option value="1">Shyju</option>
    <option value="2">Sean</option>
</select>

Çoklu seçimde seçilen seçenekleri ayarlama

Tek seçime benzer şekilde, EmployeeIdsözellik değerini istediğiniz değer dizisine ayarlayın .

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "11"},
        new SelectListItem {Text = "Tom", Value = "12"},
        new SelectListItem {Text = "Jerry", Value = "13"}
    };
    vm.EmployeeIds= new int[] { 12,13} ;  
    return View(vm);
}

Bu, sayfa oluşturulduğunda çoklu seçim öğesinde Tom ve Jerry seçeneğini seçer.

Öğe listesini aktarmak için ViewBag kullanma

Eğer görünüme seçenekler listesini geçirmek için bir koleksiyon türü özelliği tutmayı tercih etmiyorsanız, bunu yapmak için dinamik ViewBag kullanabilirsiniz. ( Bu benim kişisel olarak önerilen yaklaşım değildir viewbag dinamiktir ve kodunuzu uncatched eğilimli olarak yazım hataları )

public IActionResult Create()
{       
    ViewBag.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "1"},
        new SelectListItem {Text = "Sean", Value = "2"}
    };
    return View(new MyViewModel());
}

ve görünümde

<select asp-for="EmployeeId" asp-items="@ViewBag.Employees">
    <option>Please select one</option>
</select>

Öğe listesini aktarmak ve seçilen seçeneği ayarlamak için ViewBag kullanma

Yukarıdaki ile aynı. Yapmanız gereken tek şey, özellik (açılır liste için bağlayıcı olduğunuz) değerini, seçmek istediğiniz seçeneğin değerine ayarlamaktır.

public IActionResult Create()
{       
    ViewBag.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "1"},
        new SelectListItem {Text = "Bryan", Value = "2"},
        new SelectListItem {Text = "Sean", Value = "3"}
    };

    vm.EmployeeId = 2;  // This will set Bryan as selected

    return View(new MyViewModel());
}

ve görünümde

<select asp-for="EmployeeId" asp-items="@ViewBag.Employees">
    <option>Please select one</option>
</select>

Öğeleri gruplama

Seçme etiketi yardımcı yöntemi, bir açılır menüde gruplama seçeneklerini destekler. Tek yapmanız gereken , eylem yönteminizde Groupher birinin özellik değerini belirtmektir SelectListItem.

public IActionResult Create()
{
    var vm = new MyViewModel();

    var group1 = new SelectListGroup { Name = "Dev Team" };
    var group2 = new SelectListGroup { Name = "QA Team" };

    var employeeList = new List<SelectListItem>()
    {
        new SelectListItem() { Value = "1", Text = "Shyju", Group = group1 },
        new SelectListItem() { Value = "2", Text = "Bryan", Group = group1 },
        new SelectListItem() { Value = "3", Text = "Kevin", Group = group2 },
        new SelectListItem() { Value = "4", Text = "Alex", Group = group2 }
    };
    vm.Employees = employeeList;
    return View(vm);
}

Görünüm kodunda değişiklik yok. select tag helper şimdi 2 optgroup item içindeki seçenekleri sunacaktır .


1
Teşekkür ederim! Bir çeşit SelectList'e dönüşüm gerçekleştirmemiz gereken eski ustura sözdizimi gibi. Tekrar teşekkürler.
Sam

7
Boş bir seçenek eklemek için bakıyordum, kullandığınız için teşekkürler<option>Please select one</option>
Serj Sagan

5
Bir kapatma </select> etiketine sahip olmanız GEREKİR - seçim etiketini <select ... /> gibi kendi kendine kapatmaya çalışırsanız çalışmaz. Ayrıca, "Lütfen birini seçin" gibi boş bir seçenek kullanırsanız, gerekli alan doğrulamasının çalışması için bu boş bir dize "" değeri vermeniz gerekir.
Andy

3
"Seçme öğesi için açık bir kapatma etiketi kullandığınızdan emin olun. Kendiliğinden kapanan etiket yaklaşımını kullanırsanız, etiket yardımcısı boş bir SELECT öğesi oluşturur!" Benim durumumda sorun buydu. Şerefe!
Mariusz

2
Bu cevaba çok çaba harcadığınız için teşekkürler!
Vidar

11

Bunun için bir arayüz ve bir <options>etiket yardımcısı oluşturdum. Bu yüzden kontrolü her doldurmam gerektiğinde IEnumerable<T>öğeleri dönüştürmek IEnumerable<SelectListItem>zorunda kalmadım <select>.

Ve bence güzel çalışıyor ...

Kullanımı şöyle bir şeydir:

<select asp-for="EmployeeId">
    <option value="">Please select...</option>
    <options asp-items="@Model.EmployeesList" />
</select>

Ve etiket yardımcısıyla çalışmasını sağlamak için bu arayüzü sınıfınızda uygulamanız gerekir:

public class Employee : IIntegerListItem
{
   public int Id { get; set; }
   public string FullName { get; set; }

   public int Value { return Id; }
   public string Text{ return FullName ; }
}

Bunlar gerekli kodlardır:

Arayüz:

public interface IIntegerListItem
{
    int Value { get; }
    string Text { get; }
}

<options>Etiket yardımcı:

[HtmlTargetElement("options", Attributes = "asp-items")]
public class OptionsTagHelper : TagHelper
{
    public OptionsTagHelper(IHtmlGenerator generator)
    {
        Generator = generator;
    }

    [HtmlAttributeNotBound]
    public IHtmlGenerator Generator { get; set; }

    [HtmlAttributeName("asp-items")]
    public object Items { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.SuppressOutput();
        // Is this <options /> element a child of a <select/> element the SelectTagHelper targeted?
        object formDataEntry;
        context.Items.TryGetValue(typeof(SelectTagHelper), out formDataEntry);

        var selectedValues = formDataEntry as ICollection<string>;
        var encodedValues = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
        if (selectedValues != null && selectedValues.Count != 0)
        {
            foreach (var selectedValue in selectedValues)
            {
                encodedValues.Add(Generator.Encode(selectedValue));
            }
        }

        IEnumerable<SelectListItem> items = null;
        if (Items != null)
        {
            if (Items is IEnumerable)
            {
                var enumerable = Items as IEnumerable;
                if (Items is IEnumerable<SelectListItem>)
                    items = Items as IEnumerable<SelectListItem>;
                else if (Items is IEnumerable<IIntegerListItem>)
                    items = ((IEnumerable<IIntegerListItem>)Items).Select(x => new SelectListItem() { Selected = false, Value = ((IIntegerListItem)x).Value.ToString(), Text = ((IIntegerListItem)x).Text });
                else
                    throw new InvalidOperationException(string.Format("The {2} was unable to provide metadata about '{1}' expression value '{3}' for <options>.",
                        "<options>",
                        "ForAttributeName",
                        nameof(IModelMetadataProvider),
                        "For.Name"));
            }
            else
            {
                throw new InvalidOperationException("Invalid items for <options>");
            }

            foreach (var item in items)
            {
                bool selected = (selectedValues != null && selectedValues.Contains(item.Value)) || encodedValues.Contains(item.Value);
                var selectedAttr = selected ? "selected='selected'" : "";

                if (item.Value != null)
                    output.Content.AppendHtml($"<option value='{item.Value}' {selectedAttr}>{item.Text}</option>");
                else
                    output.Content.AppendHtml($"<option>{item.Text}</option>");
            }
        }
    }
}

Bazı yazım hataları olabilir ama bence amaç çok açık. Biraz düzeltmek zorunda kaldım.


4

IHtmlHelper.GetEnumSelectList öğesini de kullanabilirsiniz .

    // Summary:
    //     Returns a select list for the given TEnum.
    //
    // Type parameters:
    //   TEnum:
    //     Type to generate a select list for.
    //
    // Returns:
    //     An System.Collections.Generic.IEnumerable`1 containing the select list for the
    //     given TEnum.
    //
    // Exceptions:
    //   T:System.ArgumentException:
    //     Thrown if TEnum is not an System.Enum or if it has a System.FlagsAttribute.
    IEnumerable<SelectListItem> GetEnumSelectList<TEnum>() where TEnum : struct;

4

Benim cevabım aşağıda gelmez soru çözmek ama ilgilidir için.

Birisi enumsınıf modeli yerine kullanıyorsa , bu örnekte olduğu gibi:

public enum Counter
{
    [Display(Name = "Number 1")]
    No1 = 1,
    [Display(Name = "Number 2")]
    No2 = 2,
    [Display(Name = "Number 3")]
    No3 = 3
}

Ve gönderirken değeri almak için bir özellik:

public int No { get; set; }

Jilet sayfasında, Html.GetEnumSelectList<Counter>()numaralandırma özelliklerini almak için kullanabilirsiniz .

<select asp-for="No" asp-items="@Html.GetEnumSelectList<Counter>()"></select>

Aşağıdaki HTML'yi oluşturur:

<select id="No" name="No">
    <option value="1">Number 1</option>
    <option value="2">Number 2</option>
    <option value="3">Number 3</option>
</select>

3

Çoklu seçim için aşağıdaki kodu kullanabilirsiniz :

<select asp-for="EmployeeId"  multiple="multiple" asp-items="@ViewBag.Employees">
    <option>Please select</option>
</select>

Ayrıca kullanabilirsiniz:

<select id="EmployeeId" name="EmployeeId"  multiple="multiple" asp-items="@ViewBag.Employees">
    <option>Please select</option>
</select>

0

Get'te:

public IActionResult Create()
{
    ViewData["Tags"] = new SelectList(_context.Tags, "Id", "Name");
    return View();
}

Postada:

var selectedIds= Request.Form["Tags"];

Görünümünde :

<label>Tags</label>
<select  asp-for="Tags"  id="Tags" name="Tags" class="form-control" asp-items="ViewBag.Tags" multiple></select>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.