Good day,
I have this problem with Html.DropDownListFor which I can't seem to work out.. It gives me the correct number of options, if I do a breakpoint in the code where it is supposed to render the list, the "SelectItemList" object contains the items with correct values, but the actual HTML it spits out is the following:
<select id="Reason_ReasonId" name="Reason.ReasonId"><option>System.Web.Mvc.SelectListItem</option>
<option>System.Web.Mvc.SelectListItem</option>
<option>System.Web.Mvc.SelectListItem</option>
<option>System.Web.Mvc.SelectListItem</option>
<option>System.Web.Mvc.SelectListItem</option>
<option>System.Web.Mvc.SelectListItem</option>
</select>
The module containts this:
public SelectList ReasonList
{
get
{
SelectList selectList;
List<SelectListItem> selectItems;
using (var db = new EscalationDataContext())
{
var reasons =
db.Reasons
.OrderBy(r => r.Reason1)
.Select(r => new SelectListItem
{
Value = r.ReasonId.ToString(),
Text = r.Reason1
});
selectItems = reasons.ToList();
selectList = new SelectList(selectItems);
}
return selectList;
}
}
The controller just creates a default instantiation and sets the default value:
public ActionResult Create()
{
EscalationModel model = new EscalationModel
{
Reason = new Reason { ReasonId = new Guid("598c28c2-877a-44fa-9834-3241c5ee9355"), Reason1 = "Taken too long" },
ActionedDate = DateTime.Now
};
return View(model);
}
Last but not least, the view:
<%: Html.DropDownListFor(m => m.Reason.ReasonId, Model.ReasonList) %>
Any ideas why it behaves like this? As I said, in the actual code (in the view) I have the correct values, but.. It doesn't like me.. Any help would be greatly appreciated, thanks in advance!
Ok.. It seems you had to specify which variable in SelectListItem was used for "Value" and which was used for "Text"..
selectList = new SelectList(selectItems);
Became..
selectList = new SelectList(selectItems, "Value", "Text");
Which seems to have done the trick!
Related
Actually i have a action which generates a viewbag in it . i am passing an object List in my ViewBag . Now in the View i want to create a dropdown through my viewbag object which i need two fields as a combined in dropdown List in mvc . e.g. my ServiceList.field1 ,ServiceList.field2 . i want both these fields combined in dropdown .
public ActionResult Add()
{
List<service> ServiceList = new List<service>();
ServiceList = GetService();
ViewBag.BackUPList = ServiceBackupList;
return View();
}
and my view contains
#Html.DropDownList("name", (SelectList)ViewBag.BackUPList, new { #class =
"form-control" })
how to combine my both fields and show in dropDown grouped separately.
e.g.
ServiceList.field1
ServiceList.field1
ServiceList.field2
ServiceList.field2
You can generate a new collection in which you concatenate two properties in to one and then construct a SelectList like:
ServiceList = GetService();
var dropDownList = ServiceList.Select(x=> new
{
Id = x.IdField,
Name = x.Field1.ToString() + x.Field2.ToString()
}).ToList();
ViewBag.BackUPList = new SelectList(dropDownList,"Id","Name");
EDIT:
As per edited question you need to generate two collection and then concatenate:
var fieldList = ServiceList.Select(x=> x.IdField1)
.Concat(ServiceList.Select(x=> x.IdField2)).ToList();
and then create a SelectList and put in ViewBag :
ViewBag.BackUPList = fieldList.Select(x =>
new SelectListItem()
{
Value = x,
Text = x
}).ToList();
and in View :
#Html.DropDownList("name",
ViewBag.BackUPList as IEnumerable<SelectListItem>,
new { #class = "form-control" })
I am trying to bind the dropdown list to the data-set coming from the data context class in mvc 6. I wrote a function to get the populated list but unable to reproduce the same using razor. Here's what I have so far. Please note that I have not created a model yet. trying to make use of the generated POCO class from the database scaffolding.
function on Layout.cshtml
#functions{
public List<HSIP.Entities.StateDetails> function1()
{
// protected readonly HSIP.Entities.HSIPContext context;
HSIP.Entities.HSIPContext hsipcontext = new HSIP.Entities.HSIPContext();
List<HSIP.Entities.StateDetails> getstatelist = (from s in hsipcontext.StateDetails
select new HSIP.Entities.StateDetails
{
StateDesc = s.StateDesc,
StateCode = s.StateCode,
StateAbbr = s.StateAbbr
}).ToList();
//SelectList list = new SelectList(getstatelist, "Region", "StateCode", "StateAbbr", "StateDesc");
return getstatelist;
}
}
Razor syntax:
#Html.DropDownList("StateDesc", #function1(), "Please select State Name");
The Razor syntax throws an error: there is no argument given that corresponds to the required formal parameter 'htmlattributes' of IHTMLHelper.Dropdownlist(string, IEnumerable, string, object).
can someone please point me in the right direction.
Thanks,
Hari
I am prefer do this:
In a controller/Model:
using System.Web.Mvc;
public List<SelectListItem> DropdownListFilter()
{
var listitem = new List<SelectListItem>();
listitem.Add(new SelectListItem { Text = "Dropdown1", Value = "0", Selected = true });
listitem.Add(new SelectListItem { Text = "Dropdown2", Value = "1", Selected = false });
listitem.Add(new SelectListItem { Text = "Dropdown3", Value = "2", Selected = false });
return listitem;
}
When I Load in the ActionResult Just add this following Line:
ViewBag.FilterDropdown = ar.DropdownListFilter().ToList();
And in the view you have to call Filter dropdown like this:
#Html.DropDownList("FilterDropdown")
Hope this help.
Firstly use a SelectListItem in your controller and pass it to your view.Then use it in Razor syntax to populate the dropdown.
List<SelectListItem> stateList = (from s in hsipcontext.StateDetails
select new HSIP.Entities.StateDetails
{
StateDesc = s.StateDesc,
StateCode = s.StateCode,
StateAbbr = s.StateAbbr
}).ToList();
View:
#Html.DropDownListFor("StateDesc", stateList ,"Please select State Name")
When I create a SelecList I wish to be able to add SelecListItem's manually and to do this I use this code:
List<SelectListItem> Provinces = new List<SelectListItem>();
Provinces.Add(new SelectListItem() { Text = "Northern Cape", Value = "NC" });
Provinces.Add(new SelectListItem() { Text = "Free State", Value = "FS" });
Provinces.Add(new SelectListItem() { Text = "Western Cape", Value = "WC" });
SelectList lstProvinces = new SelectList(Provinces);
Instead of this :
var lstProvinces = new SelectList(new[] { "Northern Cape", "Free State", "Western Cape" });
After I created the SelectList, I pass it to the DropDownListFor via the ViewBag :
Html.DropDownListFor(m => m.StartPointProvince, (SelectList)ViewBag.Provinces)
However when I create the SelectList using the first method, it doesn't work - It adds the 3 values to the dropdown list, but all the values display as:
*screenshot of output
However when I use the second method, it works fine.
I wish to use the first method because i want to be able to specify the Text AND value of each item.
The problem is that SelectList(IEnumerable) constructor doesn't accept SelectListItem's (at least not as SelectListItem to add to its Items collection). It simply accepts collection of some arbitrary objects that will be used to generate completely unrelated internal SelectListItems collection.
If you want, you can use SelectList(IEnumerable, string, string) constructor in such way:
List<SelectListItem> Provinces = new List<SelectListItem>();
Provinces.Add(new SelectListItem() { Text = "Northern Cape", Value = "NC" });
Provinces.Add(new SelectListItem() { Text = "Free State", Value = "FS" });
Provinces.Add(new SelectListItem() { Text = "Western Cape", Value = "WC" });
this.ViewBag.Provinces = new SelectList(Provinces, "Value", "Text");
It will work. But it is unnecessary, because you create complex SelectListItem items that won't be used by the SelectList - it will just treat them as any other data object.
In the same way you can just use some other simpler class in place of SelectListItem:
public class SelectListModel
{
public String Text { get; set; }
public String Value { get; set; }
}
...
Provinces.Add(new SelectListModel() { Text = "Northern Cape", Value = "NC" });
Use DropDownList and name it the same as the model's property name. Mine is "ItemType"
#Html.LabelFor(model => model.ItemType, new { #class = "control-label" })
#Html.DropDownList("ItemType", (IEnumerable<SelectListItem>)ViewBag.ItemTypes, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ItemType, null, new { #class = "text-danger" })
var types = new List<SelectListItem>();
types.Add(new SelectListItem() { Text = "Select...", Value = string.Empty });
types.Add(new SelectListItem() { Text = "OTC", Value = "0" });
types.Add(new SelectListItem() { Text = "Generic", Value = "1" });
types.Add(new SelectListItem() { Text = "Brand", Value = "2" });
types.Add(new SelectListItem() { Text = "Non-Merchandise", Value = "9" });
ViewBag.ItemTypes = types;
[Required(ErrorMessage = "Item Type is required")]
public Int32 ItemType { get; set; }
you can change your code from
SelectList lstProvinces = new SelectList(Provinces);
to
SelectList lstProvinces = new SelectList(Provinces, "Value", "Text");
and it will display provinces correctly.
You do not need using SelectList.
Instead, put List<SelectListItem> Provinces into ViewBag and return ViewBag.
Then on the View put:
#Html.DropDownList("Dropwonlist", (IEnumerable<SelectListItem>)ViewBag.YourData)
Considering the number of views on this topic, I thought it might help others in giving some further examples of which the option you chose depends on the desired contents of the select list.
I usually prefer to keep the assignment of select dropdown options in a seperate class which is more manageble when creating longer lists, it's also handy to use the same class of optons for more common applications across the app.
C# Class
public class CustomFormsSelectDropdownParams
{
public static IEnumerable<SelectListItem> Example1ItemWidth { get; private set; }
public static IEnumerable<SelectListItem> Example2ItemWidth { get; private set; }
public static List<SelectListItem> Example3ItemWidth { get; private set; }
static CustomFormsSelectDropdownParams()
{
// ---------
// Exmaple 1
// ---------
// This is OK if you only have a
// relatively small amount of options to write.
Example1ItemWidth = new SelectListItem[]
{
// First item different to the remaining range.
new SelectListItem ("100%", "100%"),
new SelectListItem ("5em", "5em"),
new SelectListItem ("6em", "6em"),
new SelectListItem ("7em", "7em"),
new SelectListItem ("8em", "8em"),
new SelectListItem ("9em", "9em"),
new SelectListItem ("10em", "10em")
};
// ---------
// Exmaple 2
// ---------
// This is more practical if you have a large amount of options.
// NOTE: using this example doesnt allow us to insert any options
// that are different from the rest, so limited use cases may apply.
Example2ItemWidth = Enumerable.Range(1, 200).Select(x => new SelectListItem
{
Value = x.ToString() + "em",
Text = x.ToString() + "em",
});
// ---------
// Exmaple 3
// ---------
// This is more practical if you have a large amount of options.
// This example also allows us to add an option that is a different
// to the remaining options in the loop.
// Our first item is bespoke so created seperately.
var firstDefaultItem = new SelectListItem("100%", "100%");
// Provides a range between 10 --> 200em
var remainingItems = Enumerable.Range(10, 191).Select(x => new SelectListItem
{
Value = x.ToString() + "em",
Text = x.ToString() + "em",
});
Example3ItemWidth = new List<SelectListItem>();
// Add out first bespoke item.
Example3ItemWidth!.Add(firstDefaultItem);
// Add the remaining items in a loop.
foreach (var item in remainingItems)
{
Example3ItemWidth.Add(new SelectListItem(item.Text, item.Value));
}
}
}
Sample HTML Code:
<div class="container-fluid">
<div class="row">
<div class="mb-3 col-3" >
<label class="form-label">Example 1</label>
<select class="form-select" asp-items="Classes.CustomForms.CustomFormsSelectDropdownParams.Example1ItemWidth"></select>
</div>
</div>
<div class="row">
<div class="mb-3 col-3" >
<label class="form-label">Example 2</label>
<select class="form-select" asp-items="Classes.CustomForms.CustomFormsSelectDropdownParams.Example2ItemWidth"></select>
</div>
</div>
<div class="row">
<div class="mb-3 col-3" >
<label class="form-label">Example 3</label>
<select class="form-select" asp-items="Classes.CustomForms.CustomFormsSelectDropdownParams.Example3ItemWidth"></select>
</div>
</div>
</div>
All three select dropdowns on the page:
Example 1:
Example 2:
Example 3:
Example 3 was the one that had niggled me for a while, I wasnt sure how to create an select options list as well as adding some other bespoke options at the same time. If i need to to add some more additional besoke options then I would simply add them in what ever order I need, either before the loop, after or in between multiple loops.
My controller looks as follow:
var _engine = new NopEngine();
var categoryService = _engine.Resolve<ICategoryService>();
var allCategory = categoryService.GetAllCategories();
List<string> ConvertedList = new List<string>();
for (int i = 0; i < allCategory.Count; i++)
{
ConvertedList.Add(allCategory[i].Name);
}
//fill the viewbag
ViewBag.CategoryList = ConvertedList;
return View("Nop.Plugin.Misc.ExportAttributes.Views.MiscExportAttributes.ExportCalculationSheet");
So basically I'm filling the ViewBag with a List of strings.
My view looks as follow:
#{
Layout = "";
}
#using Telerik.Web.Mvc.UI;
#model ExportCalculationSheetModel
#using Nop.Plugin.Misc.ExportAttributes.Models;
#using Nop.Web.Framework;
#using Nop.Core.Domain.Catalog;
#using (Html.BeginForm())
{
<table class="adminContent">
<tr>
<td colspan="2">
<b>Filter op Categorie:</b>
</td>
</tr>
<tr>
<td class="adminTitle">
#Html.NopLabelFor(model => model.searchCategory):
</td>
<td class="adminData">
#Html.DropDownListFor(x => x.searchCategory, new SelectList(ViewBag.CategoryList, "Name"))
</td>
</tr>
</table>
This works, the DropDownList gets filled with the correct values. But I don't think that the ViewBag is "Best-Practice", I heard something about using a Model to select the List from, I already added a reference to the model in the view:
#model ExportCalculationSheetModel
How can I fill the list at the model class and use it in my view?
I already tried to fill the model class the following way, but that didn't work out:
public List<string> AllCategories
{
get
{
return AllCategories;
}
set
{
var _engine = new NopEngine();
var categoryService = _engine.Resolve<ICategoryService>();
var allCategory = categoryService.GetAllCategories();
List<string> ConvertedList = new List<string>();
for (int i = 0; i < allCategory.Count; i++)
{
ConvertedList.Add(allCategory[i].Name);
}
AllCategories = ConvertedList;
}
}
So the two primary questions are:
How do I fill the list at the model page?
How do I connect the list at my model page to the dropdownlist at my view?
Thanks in advance!
The only thing DropDownListFor needs is an IEnumerable<SelectListItem> (i.e., that could be a list/collection/queryable/etc.). The problem right now is that you simply have a list string instead of SelectListItem. That's easy remedied with a little LINQ-fu:
#Html.DropDownListFor(x => x.searchCategory, Model.AllCategories.Select(m => new SelectListItem { Value = m, Text = m }))
However, the better approach would be to simply have AllCategories return a list of SelectListItems off-the-bat (assuming it's only being used for populating the dropdown list).
private IEnumerable<SelectListItem> allCategories;
public IEnumerable<SelectListItem> AllCategories
{
get
{
if (allCategories == null)
{
var _engine = new NopEngine();
var categoryService = _engine.Resolve<ICategoryService>();
allCategories = categoryService.GetAllCategories().Select(m =>
new SelectListItem { Value = m.Name, Text = m.Name });
}
return allCategories;
}
// You don't need a setter
}
The first time AllCategories is accessed, the associated private variable, allCategories, will be null, so your service spins up and the list of categories is fetched. Select is used to cast the returned categories into a collection of SelectListItems. If you category has something like an Id property, you should use that for Value instead of Name. Any subsequent accesses of AllCategories will simply return the value stored in the private without hitting the database again.
Bonus Pro Tip
If you actually do need to use a for loop for something like this, you don't need to create a new list, add items to the list in the loop, and then return that list. It's easier to just use yield. For example:
public IEnumerable<int> Numbers
{
for (int i = 0; i < 10; i++)
{
yield return i;
}
}
Change
List<string> ConvertedList = new List<string>();
to
List<SelectList> ConvertedList = new List<SelectList>();
do not need for loop . you can directly add the database return list values to ConvertedList
look this sample's
Binding Data To DropDownList MVC Razor
here is a good sample
May be you can try this:
Starting with a Dictionary in the Model
public class YourOptions
{
public Dictionary<int, string> Option { get; set; }
public YourOptions()
{
Option = new Dictionary<int, string>()
{
//Here you should put your code, this is an example
{ 0, "Option 1"},
{ 1, "Option 2"},
{ 2, "Option 3"},
{ 3, "Option 4"},
{ 4, "Option 5"},
//Here you should put your code, this is an example
};
}
In the View
#Html.DropDownListFor(model => model.Option.Keys,
new SelectList(
Model.Option,
"Key",
"Value"))
Sorry for my bad english! I hope this help you!
In my viewData I have an IList mls.
I want to use this to show in a dropdown. Like so:
<%= Html.DropDownList("ml3Code",
new SelectList(Model.Mls, "Code", "Description", Model.Ml3.Code ?? ""),
Model.T9n.TranslateById("Labels.All"),
new { #class = "searchInput" })%>
This works fine, until there's a myObject.Code == VOC<420 g/l.
I would have expected that an HTML helper would encode its values, but it doesn't.
How should I approach this problem? The only thing I can come up with is first making a dupe list of the objects with encoded values and then feeding it to the selectlist. This would be really bothersome.
P.S. I hope Phill H. and his team will have a long and thorough look at the encoding for asp.net-mvc 2.0...
I'm puzzled. The question "Do ASP.NET MVC helper methods like Html.DropDownList() encode the output HTML?" was asked on SO before, and the answer was "Yes" - and the source-code from the MVC framework was cited to back this assertion up.
Well, you can roll your own Html helper, but if you're like me you won't want to do that.
To me, I see two options here:
Write your select element in plain view without the helper. I've never felt the helpers provide you much save for highlighting an element when an error occurs.
Patch the select box on the client when the page loads, as in:
function encodeHtml(str)
{
var encodedHtml = escape(str);
encodedHtml = encodedHtml.replace(///g,"%2F");
encodedHtml = encodedHtml.replace(/\?/g,"%3F");
encodedHtml = encodedHtml.replace(/=/g,"%3D");
encodedHtml = encodedHtml.replace(/&/g,"%26");
encodedHtml = encodedHtml.replace(/#/g,"%40");
return encodedHtml;
}
window.onload = function()
{
var ml3Code = document.getElementById("ml3Code");
for(var i = 0; i < ml3Code.options.length; ++i)
{
ml3Code.options[i].value = encodeHtml(ml3Code.options[i].value);
}
};
It's a hack, I know. I strongly prefer the first choice.
This is encoded. But dont check with firebug - It shows values decoded.
Check in ViewSource of the Browser and things are encoded.
Controller
public List<CategoryInfo> GetCategoryList()
{
List<CategoryInfo> categories = new List<CategoryInfo>();
categories.Add(new CategoryInfo { Name = "Food<äü", Key = "VOC<420 g/l", ID = 2, Uid = new Guid("C0FD4706-4D06-4A0F-BC69-1FD0FA743B07") });
}
public ActionResult Category(ProductViewModel model )
{
IEnumerable<SelectListItem> categoryList =
from category in GetCategoryList()
select new SelectListItem
{
Text = category.Name,
Value = category.Key
};
model.CategoryList = categoryList;
return View(model);
}
View
<%= Html.DropDownList("Category" , Model.CategoryList) %>
Model
public class ProductViewModel
{
public IEnumerable<SelectListItem> CategoryList { get; set; }
public List<CategoryInfo> Categories { get; set; }
}
HTML
<select id="Category" name="Category"><option value="VOC<420 g/l">Food<äü</option>
</select>