DropDownListFor not working with nested list - asp.net-mvc

My DropDownListFor not bind selected item.
This is correct model:
public class DeliveryOrderModel
{
public BoxInfo Boxes { get; set; }
public class BoxInfo
{
public long? CountryID { get; set; }
public IEnumerable<SelectListItem> Countries { get; set; }
}
}
And in this model problem:
public class DeliveryOrderModel
{
public List<BoxInfo> Boxes { get; set; }
public class BoxInfo
{
public long? CountryID { get; set; }
public IEnumerable<SelectListItem> Countries { get; set; }
}
}
This is SelectItems
var Countries = new SelectList(new[]
{
new { CountryID = 1, Text = "Name1" },
new { CountryID = 2, Text = "Name2" },
new { CountryID = 3, Text = "Name3" }
} ,"CountryID","Text");
This dropdown work with first model:
Html.DropDownListFor(model => model.Boxes.CountryID, Model.Boxes.Countries)
And this is trouble dropdown:
Html.DropDownListFor(model => model.Boxes[0].CountryID, Model.Boxes[0].Countries)

First thought - SelectList is a collection, not an array, so you may need something like:
Html.DropDownListFor(model => model.Boxes.First().CountryID,
Model.Boxes.First().Countries)
May also need a lamda expresson for the .First
ADDITION
Model might be like
public class DeliveryOrderModel
{
public List<BoxInfo> Boxes { get; set; }
public class BoxInfo
{
publix Box myBox { get; set; }
public long? CountryID { get; set; }
}
}
CountryList becomes a separate and independent SelectList ViewModel.
And finally the view
Html.DropDownListFor(model => model.Boxes[0].CountryID, Countries)
Or a ForEach to iterate through the boxes, or ...
OK?

Related

DropDownListFor, selected = true doesn't work

Select doesn't work for me with DropDownListFor. Can anyone help me?
I have musiccategories and artists that belong to one musiccategory. On my page I want to show artist details, and I want the dropdownlist to load all musiccategories with the specified artists music category selected. But I can't make one specified option in the drop down list selected, the first option is always selected at first.
My controller:
public ActionResult Index()
{
ClassLibrary.Artist a = GetArtist();
System.Collections.Generic.List<System.Web.Mvc.SelectListItem> items = getGenres();
string genre = a.MusicCategory;
foreach (SelectListItem sli in items)
{
if (sli.Text == genre)
{
sli.Selected = true;
}
}
ViewBag.MusicCategory = items;
return View(a);
}
My first model:
public class MusicCategory
{
public int MusicCategoryID { get; set; }
public string MusicCategoryName { get; set; }
}
My secound model:
public class Artist
{
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string Description { get; set; }
public string MusicCategory { get; set; }
public int MusicCategoryID { get; set; }
public int Contact { get; set; }
public string InformationToCrew { get; set; }
public string Agreement { get; set; }
public string WantedStage { get; set; }
public string AgreementAccepted { get; set; }
public string PublishingStatus { get; set; }
public string ApplicationStatus { get; set; }
public int? ActiveFestival { get; set; }
public string ImageURL { get; set; }
public string URL { get; set; }
public string FacebookEvent { get; set; }
public int Score { get; set; }
public List<GroupMember> GroupMembers { get; set; }
}
My view:
#Html.DropDownListFor(model => model.MusicCategory, (System.Collections.Generic.List<System.Web.Mvc.SelectListItem>)ViewBag.MusicCategory)
DropDownListFor, selected = true doesn't work
Yup.
But I can't make one specified option in the drop down list selected, the first option is always selected at first.
When you use
// I don't recommend using the variable `model` for the lambda
Html.DropDownListFor(m => m.<MyId>, <IEnumerable<SelectListItem>> ...
MVC Ignores .selected and instead verifies the m.<MyId> value against the values in <IEnumerable<SelectListItem>>.
public class DropDownModel
{
public int ID3 { get; set; }
public int ID4 { get; set; }
public int ID5 { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
}
public ActionResult Index()
{
var model = new DropDownModel
{
ID3 = 3, // Third
ID4 = 4, // Second
ID5 = 5, // There is no "5" so defaults to "First"
Items = new List<SelectListItem>
{
new SelectListItem { Text = "First (Default)", Value = "1" },
new SelectListItem { Text = "Second (Selected)", Value = "2", Selected = true },
new SelectListItem { Text = "Third", Value = "3" },
new SelectListItem { Text = "Forth", Value = "4" },
}
};
return View(model);
}
<div>#Html.DropDownListFor(m => m.ID3, Model.Items)</div>
<div>#Html.DropDownListFor(m => m.ID4, Model.Items)</div>
<div>#Html.DropDownListFor(m => m.ID5, Model.Items)</div>
Result:
dotnetfiddle.net Example
Maybe it has something to do with the way you populate your selec list items or your model.
You can take a look at this post :
How can I reuse a DropDownList in several views with .NET MVC

Adding dynamic attributes to a model

I can't wrap my mind around this issue and haven't found the correct search keys yet:
I would like to have several categories of items in which all items have specific attributes. Those attributes (text fields, dropdowns, or checkboxes) should be added to a category and I want to edit and save those attributes for each item.
I'm working with MVC 4 and code-first EF5. How can I implement this?
My first approach were several classes like Text, Dropdown that were inherited from an abstract Attribute class and a Category class like this:
public class Category
{
[Key]
public int CategoryId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Item> Items { get; set; }
public virtual ICollection<Attribute> Attributes { get; set; }
}
But then I had no idea to proceed. Am I on the right way or completely wrong? Can someone give me a few hints I can search for?
Edit
Ultimately I'm trying to build a list of hifi devices. Speakers have different attributes than amplifier and those have different attributes to tape recorders. I would like to give a unified look for the details of each device and pre-define specific attributes to that category with an additional free-for-all text area. Speaker XYZ is my item, Speaker my category and dB an attribute.
Ok so this question is basically about the data design.
First, I assume that the rule is:
One item has one category
One category has many attributes
One item has many attributes associated with the category
For rule no.1, it is good enough in your design. (simplified example)
public class Category{
public IEnumerable<Item> Items{get;set;}
}
public class Item{
public Category Category{get;set;}
}
Its clear enough.
For rule no.2, I think you should make a CategoryAttribute class. It holds the relation between one to many Category and Attribute. Basically, CategoryAttribute is a master, whereas the children will be ItemAttribute.
public class Category{
public IEnumerable<CategoryAttribute> CategoryAttributes{get;set;}
}
public class CategoryAttribute{
public Category Category{get;set;}
public string CategoryName{get;set;}
public string DefaultValue{get;set;} // maybe a default value for specific
// attribute, but it's up to you
public IEnumerable<ItemAttribute> ItemAttributes{get;set;}
}
The IEnumerable<ItemAttribute> is the one to many relation between category attribute and item attribute.
For rule no.3, the the ItemAttribute described in rule no.2 will be represented attribute owned by each item.
public class Item{
public IEnumerable<ItemAttribute> ItemAttributes{get;set;}
}
public class ItemAttribute{
public Item Item {get;set;} // it owned by one attribute
public CategoryAttribute{get;set;} // it owned by one category attribute
}
I don't quite sure about how to represent relation or primary and foreign key in code first. Hopefully I can enhance my answer if needed (and if I able). But hopefully my illustration about relations and the class designs for each objects.
I think something like this may work for you...
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Item> Items { get; set; }
public virtual ICollection<Attribute> Attributes { get; set; }
}
public class Item
{
public int ItemId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
public virtual ICollection<ItemAttribute> ItemAttributes { get; set; }
}
public class Attribute
{
public int AttributeId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<ItemAttribute> ItemAttributes { get; set; }
}
public class ItemAttribute
{
public int ItemId { get; set; }
public int AttributeId { get; set; }
public Item Item { get; set; }
public Attribute Attribute { get; set; }
public string Value { get; set; }
public int ValueInt{ get; set; }
// etc.
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ItemAttribute>()
.HasKey(x => new { x.ItemId, x.AttributeId });
modelBuilder.Entity<ItemAttribute>()
.HasRequired(x => x.Item)
.WithMany(x => x.ItemAttributes)
.HasForeignKey(x => x.ItemId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<ItemAttribute>()
.HasRequired(x => x.Attribute)
.WithMany(x => x.ItemAttributes)
.HasForeignKey(x => x.AttributeId)
.WillCascadeOnDelete(false);
// AttributeCategories is created for you - but you can do the same as ^ above to customize
// just change 'ICollection<Category> Categories' to collection of 'ItemAttribute'
}
// use it like e.g.
var item = new Item { Name = "ItemTest", };
var attribute = new Attribute { Name = "attributeTest", };
item.ItemAttributes = new List<ItemAttribute>
{
new ItemAttribute { Item = item, Attribute = attribute, Value = "test", },
};
var category = new Category
{
Name = "cat1",
Items = new[]
{
item,
new Item{ Name = "Item1", },
new Item{ Name = "Item2", },
new Item{ Name = "Item3", },
new Item{ Name = "Item4", },
new Item{ Name = "Item5", },
},
Attributes = new[]
{
attribute,
new Attribute{ Name = "att1", },
new Attribute{ Name = "att2", },
}
};
db.Categories.Add(category);
db.SaveChanges();
var categories = db.Categories.ToList();
ItemAttribute is used to connect and store values.
And you're going to need to further adjust as per your requirements.
I actually never worked with code first approach, but I can give you some idea about how this scenario can be handled...To me, it looks that Item is the major one instead of Category. So you can have this structure...
public class Category
{
[Key]
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public string CategoryDescription { get; set; }
// use attributes here if you want them for Category
//public Dictionary<string, string> ItemnAttributes { get; set; }
}
public class MyItem
{
[Key]
public int ItemId { get; set; }
public string ItemName { get; set; }
public string ItemDescription { get; set; }
public Category ItemnCatagory { get; set; }
public Dictionary<string, string> ItemnAttributes { get; set; }
}
Hope this helps..

Multiple dropdowns on mvc view

How can I create multiple dropdowns in my view with values coming from my database? I can get one dropdown, but how do I add another one?
public class MyModel
{
public Category Category { get; set; }
public IEnumerable<SelectListItem> List { get; set; }
}
public ActionResult Page()
{
var query = model.MyModel.Select(c => new SelectListItem
{
Value = c.ModelDescription,
Text = c.ModelDescription
});
var model = new MyModel
{
List = query.AsEnumerable()
};
return View(model);
}
You can just add more properties to contain your other selectlistitems
public class MyModel
{
public Category Category { get; set; }
public IEnumerable<SelectListItem> List1 { get; set; }
public IEnumerable<SelectListItem> List2 { get; set; }
public IEnumerable<SelectListItem> List3 { get; set; }
}
And just run other queries you need to populate them. And then you can just use them in the view.

Object reference not set to an instance of an object on DropDownListFor

This is driving me crazy! I am trying to create a drop down list that gets it's values from the database. I am new to MVC, so it's probably something simple, but I can't figure it out. Please help!
View Model:
public class LoadInputModel
{
public GeoRegion GeoRegion { get; set; }
public System.Guid Id { get; set; }
public IEnumerable<GeoRegion> Description { get; set; }
}
Here is my controller:
[HttpPost]
public ActionResult LoadShape(LoadInputModel LoadInputModel)
{
LoadInputModel.Description = db.GeoRegions.Select(a => a);
return View(LoadInputModel);
}
Here is my htmlhelper:
#Html.DropDownListFor(m => m.Description,Model.Description.Select(c => new SelectListItem { Text = c.Description, Value = c.Id.ToString() }), "-----Select Category----")
I guess your Description property value is null, So you may need to initialize it before assigning some values to that
if( LoadInputModel.Description==null)
{
LoadInputModel.Description=new List<GeoRegion>();
}
LoadInputModel.Description = db.GeoRegions.Select(a => a);
Or you can do it in the class level itself so taht you dont need to do in many places
public class LoadInputModel
{
public GeoRegion GeoRegion { get; set; }
public System.Guid Id { get; set; }
public IEnumerable<GeoRegion> Description { get; set; }
public LoadInputModel()
{
if(Description==null)
{
Description=new List<GeoRegion>();
}
}
}

DropDownList in wrapper class for two classes

My problem started when I wrap three classes
the first class is
[Bind(Exclude="ID")]
public class Material
{
public string MaterialName { get; set; }
}
the second class is
[Bind(Exclude="ID")]
public class ExameState
{
public string ExamState { get; set; }
}
the third class is
[Bind(Exclude="ID")]
public class Exams
{
public string ExamsName { get; set; }
public DateTime CreationDate { get; set; }
public DateTime StartingDate { get; set; }
public int Period { get; set; }
public int ExamStateID { get; set; }
public int MaterialID { get; set; }
public int GroupID { get; set; }
public int QuestionState { get; set; }
public int TeacherID { get; set; }
public int ExamMarkState { get; set; }
public string Password { get; set; }
}
wrapper class is
public class Examswrapper
{
public Material material { get; set; }
public ExameState examstate { get; set; }
public Exam exam { get; set; }
}
I need to display dropdownlist for Material with datavalue=MaterialName
and key=ID in view build on Examswrapper class
I am trying this
how to make it
and thank you for your advice
new error :
System.NullReferenceException: Object reference not set to an instance of an object.
There is a problem with your view model because the Material property should be a collection if you want a drop down list. Also your Material class is missing an ID property. So:
public class Material
{
public string ID { get; set; }
public string MaterialName { get; set; }
}
public class ExamsViewModel
{
public string SelectedMaterialId { get; set; }
public IEnumerable<Material> Materials { get; set; }
... // some other properties
}
and then in your strongly typed view:
<%= Html.DropDownListFor(
// This is the property that will hold the selected value
x => x.SelectedMaterialId,
// Build the select list based on the Model.Materials collection
new SelectList(
Model.Materials.Select(material => new SelectListItem
{
Value = material.ID,
Text = material.MaterialName
}),
"Value", "Text"
)
) %>
#Html.DropDownListFor(model => model.material,
Model.material.Select(
x => new SelectListItem
{
Text = x.MaterialName,
Value = x.Id
}
))

Resources