问题
I am working on a site where I have a MultiSelectList of categories. Each item can belong to multiple categories, and obviously each category can have many items. I have it selecting the correct items in the dropdownlist in my view. But once I save, I can't figure out how to save the selected items back into the model.
Here is my model:
public class WebItem
{
public string ImId { get; set; }
public string itemRef { get; set; }
public string name { get; set; }
public string Image { get; set; }
public string NUTS { get; set; }
public string description { get; set; }
public string ingredients { get; set; }
public string allergens { get; set; }
public string price { get; set; }
public string saleprice { get; set; }
public string quantity { get; set; }
private const string DEFAULT_USERNAME = "amyb";
private string _username = DEFAULT_USERNAME;
public string username {
get { return _username; }
set { _username = value; }
}
[Display(Name = "Active?")]
public bool active { get; set; }
[Display(Name = "Order online?")]
public bool orderonline { get; set; }
[Display(Name = "Food?")]
public bool isfood { get; set; }
[Display(Name = "Frozen?")]
public bool isfrozen { get; set; }
[Display(Name = "Overstock?")]
public bool isoverstock { get; set; }
public string activedate { get; set; }
//public int[] catIDs { get; set; }
public List<Category> Categories { get; set; }
public IEnumerable<SelectListItem> categories { get; set; }
private List<int> selectedCategories;
public List<int> SelectedCategories
{
get
{
if (selectedCategories == null)
{
selectedCategories = Categories.Select(m => int.Parse(m.catID)).ToList();
}
return selectedCategories;
}
set { selectedCategories = value; }
}
}
public class Category
{
public Category()
{
}
public Category(string catID, string name, string longname)
{
this.catID = catID;
this.name = name;
this.longname = longname;
}
public string catID { get; set; }
public string name { get; set; }
public string longname { get; set; }
}
Relevant controller code:
public ActionResult UpdateItem(string ImId)
{
WebItem item = new WebItem();
List<Category> categories = HomeModel.getAllCategories();
//var selectCategories = categories.Select(c => new
//{
// CategoryID = c.catID,
// CategoryName = c.longname
//}).ToList();
//item.categories = new MultiSelectList(selectCategories, "CategoryID", "CategoryName");
item.categories = categories.Select(c => new SelectListItem
{
Text = c.name,
Value = c.catID
});
if (ImId != null && !ImId.Equals(""))
{
string query = "SELECT 'Image', 'NUTS', ...";
MySqlConnection con;
//WebItem item = new WebItem();
try
{
con = new MySqlConnection();
con.ConnectionString = appConfig._...;
con.Open();
item = con.Query<WebItem>(query, new { imid = ImId }).FirstOrDefault();
string activedate = item.activedate;
if (activedate.Contains(' '))
{
string[] activedates = activedate.Split(' ');
item.activedate = activedates[0];
}
//List<Category> categories = HomeModel.getAllCategories();
//var selectCategories = categories.Select(c => new
//{
// CategoryID = c.catID,
// CategoryName = c.longname
//}).ToList();
query = "SELECT ...";
try
{
item.SelectedCategories = con.Query<int>(query, new { pid = ImId }).ToList();
}
catch (MySqlException ex)
{
}
//item.categories = new MultiSelectList(selectCategories, "CategoryID", "CategoryName", item.catIDs);
}
catch (MySqlException ex)
{
// show error somehow
//return View(ex.Message);
}
}
return View(item);
}
[HttpPost]
public ActionResult UpdateItem(WebItem item)
{
string result = HomeModel.insertUpdateItem(item);
TempData["Message"] = item.name + " has been inserted/updated.";
return RedirectToAction("WebItems");
}
And the relevant part of my view:
<div class="form-group">
@Html.LabelFor(model => model.categories, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@*@Html.DropDownList("category", (MultiSelectList)Model.categories, new { multiple = "multiple", htmlAttributes = new { @class = "form-control" } })*@
@Html.ListBoxFor(m => m.SelectedCategories, Model.categories)
@Html.ValidationMessageFor(model => model.categories, "", new { @class = "text-danger" })
</div>
</div>
I don't currently have any code dealing with the categories in my [HttpPost] section of my action. But I'm sure I need something there. And I'm not sure if my model or view are right either.
回答1:
You may add a new property of array type to your vie wmodel to store the selected options from the multi select box.When the form is posted, MVC Model binding will properly bind the selected values to an object of this view model as long as we have that in our HttpPost action method as a parameter.
public class CreateWebItem
{
public string Name{ get; set; }
public List<SelectListItem> Categories { set; get; }
public int[] SelectedCategories { set; get; }
//Add other properties NEEDED FOR THE VIEW
}
And in your GET action
public ActionResult Create()
{
var vm = new CreateWebItem();
//Hard coded for demo. you may replace with values from db
v.Categories = new List<SelectListItem>
{
new SelectListItem { Value="1", Text="Dinner" },
new SelectListItem { Value="2", Text="Lunch" },
new SelectListItem { Value="3", Text="Snacks" },
new SelectListItem { Value="4", Text="Drinks" }
};
return View(vm);
}
And in your razor view which is strongly typed to the CreateWebItem
view model.
@model CreateWebItem
@using (Html.BeginForm())
{
<label>FirstName </label>@Html.TextBoxFor(d => d.Name)
<label>Categories</label>
@Html.ListBoxFor(s=>s.SelectedCategories,Model.Categories)
<input type="submit" value="Add" />
}
And when the form is posted, you can use the SelectedCategories
property to get an array of Id's (of the selected options)
[HttpPost]
public ActionResult Index(CreateWebItem model)
{
//read model.SelectedCategories array
// to do : Save to somewhere and do a redirect (PRG pattern)
}
来源:https://stackoverflow.com/questions/34299110/saving-selected-multiselectlist-items-back-to-the-model