0

我的场景:我的模型是“项目”,其中包含 0 个或多个税(模型“税”)

"Item" --> 有 0 或 n --> "Tax"

我有一个名为“VMItem”的 MVC 视图模型,它有一个对象为“Item”、所有税款(“TaxDic”)和选定的税款(“Taxes”)。MVC 页面绑定到此视图模型(“ViewItem”)。

要求:我希望 MVC 显示所有税款的列表框,并允许用户在创建项目时为每个项目选择相关税款。

下面是我的代码,

参考以下代码,用于Taxes的ListBox不是必填字段。但是当我在 ListBox 上提交带有一些选择的表单时,它会在 ListBox 周围显示红色框,如果我在 ListBox 上没有选择任何内容并提交,它似乎没有错误。

请看下面的场景..如果有更好的方法来实现这一点,请有人指导我。

模型

public class Item 
{
    [Display(Name="Item ID")]
        public virtual Guid ItemID { get; set; }

        [Required]
        [Display(Name = "Name")]
        public virtual string Name { get; set; }

        [Required]
        [Display(Name="Price")]
        public virtual decimal Price { get; set; }

        public virtual IEnumerable<Tax> Taxes { get; set; }

}

查看模型

public class VMItem
{
    public Item Item { get; set; }
        public IEnumerable<Tax> Taxes { get; set; }
        public IEnumerable<SelectListItem> TaxDic { get; set; }
}

在控制器类中生成选择列表项的函数

private VMItem GenerateViewModel(Item Item)
{
        IEnumerable<Tax> Taxes = TaxServices.FindAll();
        IList<SelectListItem> taxDic = new List<SelectListItem>();

        // Generating Taxes and taxDic here..

        VMItem VmItem = new VMItem
        {
            Item = Item,
            Taxes = Taxes,
            TaxDic = taxDic
        };

        return VmItem;
    }

控制器动作

// GET: /Product/Add

public ActionResult Add()
{
    return View(GenerateViewModel(new Item()));
}

[HttpPost]
public ActionResult Add(VMItem collection)
{
    Item item = new Item();
        try
        {
         if(ModelState.IsValid)
         {
        item = collection.Item;        

        var taxes = collection.Taxes;
            return View(GenerateViewModel(collection.Item));                
             }
         // else..

    }
        // catch...
}

意见

<% using (Html.BeginForm()) { %>

<!-- more codes for other fields -->

<%: Html.ListBoxFor(model => model.Taxes, Model.TaxDic) %>

<!-- submit button goes below -->

<% } %>
4

2 回答 2

1

这看起来像一个多对多的关系,所以首先检查您的税类是否如下所示:

public class Tax
{
  public Guid TaxId { get; set;}
  public virtual ICollection<Item> Items { get; set;}
}

然后在上下文类的 OnModelCreating 函数中添加:

modelBuilder.Entity<Item>()
     .HasMany(i => i.Taxes).WithMany(t => t.Items)
     .Map(t => t.MapLeftKey("ItemId")
         .MapRightKey("TaxId")
         .ToTable("ItemsTaxes"));

视图模型

public class ItemTaxViewModel
{
   public Item item { get; set; }
   public virtual ICollection<AssignedTaxes> Taxes { get; set; }
}

public class AssignedTaxes
{
  public int TaxId { get; set; }
  public bool Assigned { get; set; }
}

控制器动作

public ActionResult Create()
{
   var newItemVM = new ItemTaxViewModel
          {
              Item = new Item(),
              Taxes = PopulateTaxes()
          };
    return View(newItemVM);
 }

[HttpPost]
public ActionResult Create(ItemTaxViewModel itemTaxViewModel)
{
   if(ModelState.IsValid)
   {
      var item = new Item();
      item = itemTaxViewModel.Item;
      AddOrUpdateTaxes(item, itemTaxViewModel.Taxes);
      context.Items.Add(item);
      context.SaveChanges();
      return RedirectToAction("Index");
   }
   return View(itemTaxViewModel);
}

辅助方法

private List<AssignedTaxes> PopulateTaxes()
{
  var taxes = context.Taxes;
  var assignedTaxes = new List<AssignedTaxes>();
  foreach(var tax in taxes)
  {
    assignedTaxes.Add(new AssignedTaxes
      {
        TaxId = tax.TaxId,
        Assigned = false
      });
  }
  return assignedTaxes;
 }

 private void AddOrUpdateTaxes(Item item, ICollection<AssignedTaxes> assignedTaxes)
 {
   foreach(var assignedTax in assignedTaxes)
   {
      if(assignedTax.Assigned)
      {
         item.Taxes.Add(context.Taxes.Single(t => t.TaxId == assignedTax.TaxId));
      }
   }
  }

/Views/Shared/EditorTemplates 下的 EditorTemplate

@model AssignedTaxes
@using projectName.ViewModels

 <fieldset>
     @Html.HiddenFor(model => model.TaxId)
     @Html.CheckBoxFor(model => model.Assigned)
 </fieldset>

看法

<div class="editor-field">
   @Html.EditorFor(model => model.Taxes)
<div class="editor-field">

似乎需要做很多工作,但它是实现多对多复选框的最简洁方法之一,这是我在阅读了许多教程后提出的。

于 2012-12-26T13:29:23.583 回答
0

@Luis,你的方式看起来不错,但它太复杂了,最后你用复选框结束了它。可能是更好的方法。我想出了一个解决方案,这对我来说很简单。我把它贴在下面。请给我一个反馈,我是否应该继续使用它或需要改进。

控制器

        IEnumerable<Tax> Taxes = _TaxServices.FindTax();
        IList<SelectListItem> taxDic = new List<SelectListItem>();
        foreach (Tax tax in Taxes)
        {
            SelectListItem item = new SelectListItem();
            item.Value = tax.TaxID.ToString();
            item.Text = tax.Name;
            taxDic.Add(item);
        }

        VMItem VmItem = new VMItem
        {
            Item = Item,
            TaxDic = taxDic,
        };

        // Adding selected taxes to the list
        IList<int> SelectedTaxes = new List<int>();
        if (Item.Taxes != null && Item.Taxes.Count > 0)
        {
            foreach (Tax tax in Item.Taxes)
            {
                SelectedTaxes.Add(tax.TaxID);
            }
        }
        VmItem.SelectedTax = SelectedTaxes;

        return view(VmItem);

看法

<%: Html.ListBoxFor(model => model.SelectedTax, Model.TaxDic) %>

控制器 [HttpPost]

    item.Taxes = new Iesi.Collections.Generic.HashedSet<Tax>();
    if (vmItem.SelectedTax.Count() > 0)
    {
        IEnumerable<int> SelectedTaxesIDs = vmItem.SelectedTax.ToList();
        foreach (int n in SelectedTaxesIDs)
        {
            item.Taxes.Add(_TaxServices.FindTax(n));
        }
    }

请对此方式进行反馈。谢谢。

于 2013-01-05T05:46:45.573 回答