在asp.net中的下拉列表中显示特定的枚举值.净Mvc

本文关键字:枚举 Mvc 显示 asp net 下拉列表 | 更新日期: 2023-09-27 18:15:02

我有一个Enum Class和4个statuses,分别是Created, Dispatched, DeliveredDelayed

目前,这四个都出现在我的Edit Delivery pagedropdown中。

我想要的是,如果我的statusCreated那么我应该ONLY能够将其更改为Dispatched,如果我的statusDispatched我应该ONLY能够将其更改为DeliveredDelayed,如果我的statusDelayed我应该ONLY能够将其更改为DispatchedDelivered

这些都应该发生在我的Edit Delivery page上。您还会注意到,我不希望Created出现在上面的任何一个列表中,因为我只需要Create Delivery

所以,基本上我想要实现的是当我的delivery status被设置为Created时,我应该只在我的Enum下拉列表中看到分派,当我希望编辑该交付时。类似地,对于分派,如果我的状态被设置为分派,那么我只想看到DeliveredDelayed。同样的Delayed,我只想看到DispatchedDelivered

我对MVC相当陌生,如果有人能提出一个解决方案,我将非常感激!

请让我知道是否需要任何额外的代码,我会把它添加到问题。

Enum类:

public enum Status
{
    Created, Dispatched, Delivered, Delayed
}

交付视图模型:

public class DeliveryVM
{
    public int? ID { get; set; }
    public Status Status { get; set; }
}

Delivery Edit View:

        <div class="form-group">
            @Html.LabelFor(model => model.Status, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EnumDropDownListFor(model => model.Status, htmlAttributes: new { @class = "form-control", @id="dropdown" })
                @Html.ValidationMessageFor(model => model.Status, "", new { @class = "text-danger" })
            </div>
        </div>

在asp.net中的下拉列表中显示特定的枚举值.净Mvc

您必须使用自定义选择列表而不是使用EnumDropDownListFor() helper方法。

首先定义一个获取下一个集合列表的策略。请参阅下面的StrategicStatesExtension类,它可以提供您所定义的各自的状态列表。类正在定义扩展方法,以便您可以以流畅的样式使用该方法。注意:保持当前状态在下一个可能的状态中显示在表单中作为默认选择项。

public static class StrategicStatesExtension
{
    public static Status[] Created
    {
        get
        {
            return new [] { Status.Created, Status.Dispatched };
        }
    }
    public static Status[] Dispatched
    {
        get
        {
            return new [] { Status.Delayed, Status.Delivered, Status.Dispatched };
        }
    }
    public static Status[] Delayed
    {
        get
        {
            return new [] { Status.Delivered, Status.Dispatched, Status.Delayed };
        }
    }
    public static Status[] GetAssociatedValidStatus(this Status currentStatus)
    {
        switch (currentStatus)
        {
            case Status.Created:
                return Created;
            case Status.Dispatched:
                return Dispatched;
            case Status.Delayed:
                return Delayed;
            case Status.Delivered:
                return Status.Delivered;
            default:
                throw new ArgumentOutOfRangeException("Invalid current state received.");
        }
    }
    public static List<SelectListItem> ToDropDownList(this Status[] sourceStates)
    {
        List<SelectListItem> items = new List<SelectListItem>();
        foreach (var item in sourceStates)
        {
            items.Add(
                new SelectListItem { 
                        Value = item.ToString("d"), // Value of enum (short)
                        Text = item.ToString() // Name of enum
                });
        }
        return items;
    }

这个策略扩展方法的用法如下:

public class DeliveryVM
{
    public int? ID { get; set; }
    public Status Status { get; set; }
    public List<SelectListItem> States { get; set; }
    public DeliveryVM()
    {
        // Sample usage: only for demo you need to call this in other method
        // e.g. where your model is being filled with data.
        this.States = Status.GetAssociatedValidStatus().ToDropDownList();    
    }
}

最后,而不是使用@Html.EnumDropDownListFor,你需要从ViewData或ModelProperty建立新的属性状态列表

从可视数据:

@Html.DropDownListFor("Statuses",
(List<SelectListItem>)ViewData["Statuses"],"value", "text", htmlAttributes: new { @class = "form-control", @id="dropdown" })

From Model属性:

@Html.DropDownListFor("Statuses",
(model.Statuses,"value", "text", htmlAttributes: new { @class = "form-control", @id="dropdown" })

EnumDropDownListFor()方法将为枚举中的每个项生成选项。相反,您需要使用' DropDownListFor()方法。

SelectList的视图模型添加一个额外的属性

public class DeliveryVM
{
  public int? ID { get; set; }
  [Required(ErrorMessage = "Please select the status")]
  public Status Status { get; set; }
  public SelectList StatusList { get; set; } // add this      
}

然后在GET方法中,基于现有的Status构建所需的选项。注意,您只需要构建一个表示枚举值的string列表,因为当您发布时,DefautModelBinder会将发布的string值转换为相应的enum值。

Delivery delivery = // get your data model
DeliveryVM model = new DeliveryVM
{ 
  ID = ... // set other properties based on data model
};
// Build list of options basd on current status
List<string> options = new List<string>();
if (delivery.Status == HealthHabitat.Models.Status.Created)
{
  model.Status = HealthHabitat.ViewModels.Status.Dispatched; // its the only choice so set as the default selection
  options.Add(HealthHabitat.ViewModels.Status.Dispatched.ToString());
}
else if (delivery.Status == HealthHabitat.Models.Status.Dispatched)
{
  options.Add(HealthHabitat.ViewModels.Status.Delivered.ToString());
  options.Add(HealthHabitat.ViewModels.Status.Delayed.ToString());
}
else if (delivery.Status == HealthHabitat.Models.Status.Delayed)
{
  options.Add(HealthHabitat.ViewModels.Status.Dispatched.ToString());
  options.Add(HealthHabitat.ViewModels.Status.Delivered.ToString());
}
model.StatusList = new SelectList(options);
return View(model);

在视图

@Html.LabelFor(m => m.Status, new { @class = "control-label col-md-2" })
@Html.DropDownListFor(m => m.Status, Model.StatusList, "Please select",  new { @class = "form-control" }) // unclear why you are changing the id attribute?
@Html.ValidationMessageFor(m => m.Status, new { @class = "text-danger" })

在POST方法中,选择的值将被正确地绑定到视图模型的Status属性

旁注:不清楚你做什么,当当前状态是Delivered(也许不呈现任何控件?),如果当前状态是Created,你只允许一个选择(Dispatched),所以似乎没有必要在这种情况下也呈现一个控件。