Adding SelectListItem manually to SelectList to use in DropDownListFor - c#

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.

Related

How to show selected value in a DropDownList Html Helper using ViewBag in C#

So I have the following scenario in which I am using two ViewBag(s):
To get the select list item
To get the particular item in concern
So it looks like this:
var currentType = "2";
List<SelectListItem> contentData = new List<SelectListItem>();
contentData.Add(new SelectListItem
{
Text = "Show 0 only",
Value = "0",
});
contentData.Add(new SelectListItem
{
Text = "Show 2 Only",
Value = "2",
});
ViewBag.currentType = currentType;
ViewBag.contentData = contentData;
Now in my Razor View, I am able to generate the DropDownList like this:
#Html.DropDownList("ContentTypeId", (IEnumerable<SelectListItem>)ViewBag.contentData, null, new { #class = "form-control" , #style = "width: 150px;" })
How can I can bind my ViewBag.currentType on the drop down list so it shows the pre selected value by default when the component is rendered?
Is it even possible to use two ViewBag value in this component ?
I tried like this:
#Html.DropDownList("ContentTypeId", (IEnumerable<SelectListItem>)ViewBag.contentData, null, new { #class = "form-control" , #style = "width: 150px;", #selected= (string)ViewBag.currentType})
But not getting the correct output.
Any tips/suggestions/solutions?
ViewBag is not working in your case, you will have to select an option manually, using Selected=true. HtmlDropDown is an outdated helper too.
Using html5 select with an asp helper is the best way to select item automatically
view
#{
var currentType = "2";
List<SelectListItem> contentData = new List<SelectListItem>();
contentData.Add(new SelectListItem
{
Text = "Show 0 only",
Value = "0",
});
contentData.Add(new SelectListItem
{
Text = "Show 2 Only",
Value = "2",
});
//or I guess you can take the from viewbag
string currentType = ViewBag.currentType;
List<SelectListItem> contentData = ViewBag.currentData
}
.....
<select class="form-control" id="levels" asp-for="#currentType"
asp-items="#contentData">
<option value="0" > Select </option>
</select>
this is working for dropdown list
#{
currentType = ViewBag.currentType;
contentData = ViewBag.contentData;
var dropDownItems = new SelectList(contentData,"Value","Text", currentType);
}
.....
#Html.DropDownList("#currentType",#dropDownItems,"Select",new { #class = "form-control" })
The SelectListItem Class has a Selected property.
You can just do :
List<SelectListItem> contentData = new List<SelectListItem>{
new SelectListItem
{
Text = "Show 0 only",
Value = "0",
},
new SelectListItem
{
Text = "Show 2 Only",
Value = "2",
Selected = true
});
I also wanted to post an answer with the attempt that I had made on this aspect and was able to achieve. I used the standard way of defining the pure HTML element instead of using the Razor helper tags. You can do this if you have dynamic elements which are not a part of your Model:
<select class="form-control" id="ContentDataId" name="ContentDataId">
#foreach (SelectListItem option in ViewBag.contentData as List<SelectListItem>)
{
<option value="#option.Value" #(option.Value == Convert.ToString(ViewBag.currentType) ? "selected='selected'" : "")>#option.Text</option>
}
</select>
The above definition will generate the same HTML if you used the helper tags. For those who have confusion using the helper tags, this is a more conventional way of generating your drop down list with dynamic ViewBag.

How Can I send selected text to controller from DropdownList

I want to send the selected text field in dropdown to the controller.
When I use the code as follows, I can send the id number to the controllers, but the value I selected in the list pass null.
In addition , if there is a registered value in the model, I want this field to be selected in the dropdownlist when the page is opened.
Controller
public ActionResult Degerlendir(int id ,string CV_STATU)
{
using (MULAKATDBEntities1 ent = new MULAKATDBEntities1())
{
CvViewModel cv = new CvViewModel();
var entData = ent.CV.FirstOrDefault(a => a.ID_CV == id);
entData.CV_STATU = CV_STATU;
ent.SaveChanges();
}
}
In View
#using (Html.BeginForm("Degerlendir", "Home", FormMethod.Post))
{
<input type="hidden" name="id" value="#Model.Cv.ID_CV" />
#Html.DropDownListFor(model => model.Cv.CV_STATU,
new List<SelectListItem> {
new SelectListItem() { Text = "Secilmedi" },
new SelectListItem() { Text = "Kabul edildi" },
new SelectListItem() { Text = "Reddedildi" } },
new {#id="cv_statu", #class = "form-control" })
<input type="submit" id="btnSubmit" value="KAYDET" class="btn btn-add" />
}
Set #name="cv_statu" within the HTML helper htmlAttributes for binding to parameters on POST like this.
Also change the controller method parameter to lowercase cv_statu. Only parameter names passed through URL routes are not case sensitive.
I am assuming that what you shared on your code for your ActionResult is already the HttpPost Action verb. There should be a proper HttpGet as well.
To solve your issue, make sure the first argument that you set on your DropDownListFor should match on the parameter of your Degerlendir
#Html.DropDownListFor(model => model.CV_STATU,
new List<SelectListItem> {
new SelectListItem() { Text = "Secilmedi", Value = "Secilmedi" },
new SelectListItem() { Text = "Kabul edildi", Value = "Secilmedi" },
new SelectListItem() { Text = "Reddedildi", Value = "Reddedildi", Selected = true} }, "Please select an option",
new {#id="cv_statu", #class = "form-control" })
As you notice, I changed your:
#Html.DropDownListFor(model => model.Cv.CV_STATU
To:
#Html.DropDownListFor(model => model.CV_STATU
Because what you set here will set the name attribute on your HTML. This will be binded on your parameter on your ActionResult of Degerlendir particularly your parameter:
string CV_STATU
Lastly, I added Value on your SelectListItem, because that will be passed on your ActionResult whatever you select on your DropDownList. To set the default selected value, just add Selected = true.

ASP.Net Select a Dropdown option (in View) based on a value returned by EF model

For a Dropdown (as a SelectList) in my View, I can successfully set the value to the Id returned by my model, but the list does not update to reflect the selected Id as the selected item.
<%var type = Model.CompanyTypeId; %>
<%= Html.DropDownList("Type", (ViewData["Types"] as SelectList),
new Dictionary<string, object>()
{
{ "class", "form-control form-input"},
{ "Id", "CoType"},
{ "Name", "CoType"},
{ "value", type },
{ "option", "selected" }
})%>
I expect the dropdown list to update the selected item to the corresponding Id
(In ChromeDev tools I can verify the Id=Model.CompanyTypeId and option="selected", but the dropdown list still shows the item selected by default.
I expect the dropdown list to update the selected item to the corresponding Id
(In ChromeDev tools I can verify the Id=Model.CompanyTypeId and option="selected", but the dropdown list still shows the item selected by default.
<select id="CoType" name="CoType" class="form-control form-input"
option="selected" value="1">
<option value="-1">- Assign Type - </option>
<option value="1">Dummy</option>
<option value="2">Test CompanyType</option>
</select>
Since you already have Model.CompanyTypeId, you can easily use Html.DropDownListFor. You don't set value on the HTML attributes.
Controller
public ActionResult Index()
{
var model = new TestModel
{
CompanyTypeId = 1
};
ViewBag.Types = new List<SelectListItem>
{
new SelectListItem { Value = "-1", Text = "-- Assign Type --" },
new SelectListItem { Value = "1", Text = "Dummy" },
new SelectListItem { Value = "2", Text = "Test" },
};
return View(model);
}
View
#Html.DropDownListFor(m => m.CompanyTypeId,
(ViewBag.Types as List<SelectListItem>),
new Dictionary<string, object>()
{
{ "class", "form-control form-input"},
{ "Id", "CoType"},
{ "Name", "CoType"}
})

DropDownListFor initial value not selected

I don't understand why the initial value is not selected when the form is loaded.
Here's my code
model.LUIsUsed = new List<SelectListItem>()
{
new SelectListItem { Value = "0", Text = "Ignore" },
new SelectListItem { Value = "1", Text = "Required" },
new SelectListItem { Value = "2", Text = "Optional" },
};
In my view
#Html.DropDownListFor(x => x.Foo[i].IsUsed, Model.LUIsUsed, new { #class= "form-control input-sm is-used" })
x.Foo[i].IsUsed value is "1", but required is not selected. I can't figure out why.
Is it because x.Foo is an array?
EDIT: When I don't use an array, it works
It looks like there's a problem with DropDownListFor inside a for loop.
I had to build a SelectList and specify the selected value.
#Html.DropDownListFor(x => x.Criterias[i].IsUsed, new SelectList(Model.LUIsUsed,"Value","Text", Model.Criterias[i].IsUsed))
It works, but I would like to know why.

how to add a selectlistitem to a selectlist

I have the following select list
public SelectList StaffList { get; set; }
I am assigning it the following,
inspectorCorrespondences.StaffList = new SelectList(userDetails, "Id", "FullName");
but I want to add in another SelectList item
var systemGeneratedUser = new SelectListItem() { Value = "-1", Text = "System Generated" };
how do I do that?
This isn't necessarily the most elegant solution, but you'll need to cast the SelectList's items to a list of SelectListItems if you want to add another SelectListItem.
var myItems = new List<SelectListItem>();
myItems.Add(new SelectListItem() { Text = "AA", Value = "11" } );
var mySelectList = new SelectList(myItems);
((List<SelectListItem>)mySelectList.Items).Add(new SelectListItem() { Text = "BB", Value = "22" });
According to the documentation, it looks like you need to initialize the SelectList with the values instead of adding them. Passing an enumerable of SelectListItem to the constructor appears to be the expected way.
It looks like you're already doing that in the sense that userDetails is already an enumeration? If so, what type of enumeration is it? You may need to add a line or two of code to transform it to an enumeration of SelectListItem objects, add yours to that, and then use that to initialize the SelectList. Maybe something like this:
var listItems = userDetails.Select(u => new SelectListItem { Value = u.Id, Text = u.FullName }).ToList();
listItems.Add(new SelectListItem() { Value = "-1", Text = "System Generated" });
// or perhaps .Insert() at position 0 instead?
inspectorCorrespondences.StaffList = new SelectList(listItems, "Value", "Text");

Categories