0

私のシナリオ:私のモデルは、0または多数の税金を含む「アイテム」です(モデル「税金」)

「品目」 --> 0 または n を持つ --> 「税金」

「アイテム」、すべての税金(「TaxDic」)、および選択された税金(「税金」)のオブジェクトを持つ「VMItem」という名前のMVCのビューモデルがあります。MVC ページは、このビュー モデル ("ViewItem") にバインドされます。

要件 : MVC にすべての税金のリスト ボックスを表示し、ユーザーがアイテムを作成するときに各アイテムに関連する税金を選択できるようにしたい。

以下は私のコードです、

次のコードを参照してください。税用の 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; }
}

コントローラークラスでSelectリスト項目を生成する関数

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

大変な作業のように思えますが、多くのチュートリアルを経て思いついた、多対多のチェックボックスを実装する最もクリーンな方法の 1 つです。

于 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 に答える