I have follwoing code
#Html.DropDownList("optionsforuser", new SelectList(new[] { "Option1", "Option2", "Option3" }), "Select")
Is there anyway to initialize a value of 100 for Option1, 200 for Option2, 250 for Option3 etc within SelectList?
Try using this Extension:
#Html.DropDownList("optionsforuser",
new SelectList(new Dictionary<string, int>
{
{"Option1", 100},
{"Option2", 200},
{"Option3", 250}
},
"Value", "Key")
)
and pass it a Dictionary<string, int> with the dataValueField and dataTextField populated with your values and text
SelectExtensions.DropDownList Method (HtmlHelper, String, IEnumerable(Of SelectListItem))
public static MvcHtmlString DropDownList(
this HtmlHelper htmlHelper,
string name,
IEnumerable<SelectListItem> selectList
)
SelectList Constructor (IEnumerable, String, String)
public SelectList(
IEnumerable items,
string dataValueField,
string dataTextField
)
For situations where I just want to hard-code select list items (i.e. not get them from some pre-defined collection), I use this handy little class:
public class BetterSelectList : List<SelectListItem>
{
public void Add(string text, object value, bool selected = false) {
this.Add(new SelectListItem {
Text = text,
Value = value.ToString(),
Selected = selected
});
}
}
Why is it "better"? It implements IEnumerable and has a multi-parameter Add method, which is all you need for the C# compiler to allow you to use dictionary-style initializers, resulting in about the most noise-free initialization possible:
var optionsForUser = new BetterSelectList {
{ "Option1", 100, true },
{ "Option2", 200 },
{ "Option3", 250 }
};
Yes you set text and value
var selections = new List<SelectListItem>();
selections.Add(new SelectListItem() { Text = "Option1", Value = "100" });
selections.Add(new SelectListItem() { Text = "Option2", Value ="200" });
Here is an MSDN article on select lists: select list
You can do it in your view like that as the others have posted, but can't you do it in the controller instead?
For example, In your view model:
public class ViewModel()
{
public List<SelectListItem> OptionsForUser{ get; set; }
}
In your controller:
var optionsForUser = new List<SelectListItem>();
optionsForUser.Add(new SelectListItem { Text = "Option1", Value = "100"});
optionsForUser.Add(new SelectListItem { Text = "Option2", Value = "200"});
optionsForUser.Add(new SelectListItem { Text = "Option3", Value = "250"});
var viewmodel = new ViewModel();
viewmodel.OptionsForUser = optionsForUser;
return view(viewmodel);
then in your view:
#Html.DropDownList("optionsforuser", Model.OptionsForUser);
Those other solutions will work too, I just think its not very "clean" to initialise your dropdown list in your view like that. But its probably a matter of taste
Related
Is there an overload for Html.DropDownList that will show a value from the model as the currently selected item? In my view I insert a model using as using statement
#using SchoolIn.Models
Then I access the model like this:
if (Model.Enrollments != null)
{
#Html.DropDownList("searchString", Model.Enrollments.FirstOrDefault().weekDays.Select(s => new SelectListItem { Text = s.ToString(), Value = s.ToString() }))
}
Here’s the code from my model:
public virtual string classDays { get; set; }
public string[] weekDays = new string[6] { "Day", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };
public string[] WeekDays
{
get { return weekDays; }
When my view loads it presents a dropdown list that I can select from, I select a day and save the selection but when it loads again, I want the previously selected item to be the default selected in the list. How can I do this? I would really appreciate any help, thanks.
It looks like you should be able to set Selected on the appropriate item:
#{
var Items = Model.Enrollments.FirstOrDefault().weekDays.Select(s =>
new SelectListItem { Text = s.ToString(), Value = s.ToString()
Selected = s.ToString().Equals(PreviouslySelectedValue)
}
);
}
#Html.DropDownList("searchString", Items)
You could also use DropDownListFor, which should set the selected item to the value of the property.
#Html.DropDownListFor(model => PreviouslySelectedValue, Items)
You might need to use DropDownListFor rather than DropDownList. Here is a constructor definition from MSDN. There are also five more overloads.
public static MvcHtmlString DropDownListFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
IEnumerable<SelectListItem> selectList
)
Try this Extension Method :
public static IEnumerable<SelectListItem> SetSelected(this IEnumerable<SelectListItem> selectList, object selectedValue)
{
selectList = selectList ?? new List<SelectListItem>();
if (selectedValue == null)
return selectList;
var vlaue = selectedValue.ToString();
return selectList.BuildList(m => m.Text, m => m.Value, null, m => String.Equals(m.Value, vlaue, StringComparison.CurrentCultureIgnoreCase));
}
Then you may call it in your view like this:
#Html.DropDownListFor(model => model.CategoryId, ((IEnumerable<SelectListItem>)ViewData["Categories"]).SetSelected(model.CategoryId))
I'm trying to bind an enum AgeRange using Html.DropDownListFor but regardless of whatever I'm choosing from View page, Controller is getting a value '0'. Can anyone help me to fix this issue?
EDIT: Controller code in place.
Enum Class:
public enum AgeRange
{
Unknown = -1,
[Description("< 3 days")]
AgeLessThan3Days = 1,
[Description("3-6 days")]
AgeBetween3And6 = 2,
[Description("6-9 days")]
AgeBetween6And9 = 3,
[Description("> 9 days")]
AgeGreaterThan9Days = 4
}
View:
#Html.DropDownListFor(
model => model.Filter.AgeRangeId,
#Html.GetEnumDescriptions(typeof(AgeRange)),
new { #class = "search-dropdown", name = "ageRangeId" }
)
Controller:
public ActionResult Search(int? ageRangeId)
{
var filter = new CaseFilter { AgeRangeId = (AgeRange)(ageRangeId ?? 0) };
}
You're close...
I'd suggest following along with this guy
You have to write an extension method for your selectlist to work.
I use this
public static SelectList ToSelectList<TEnum>(this TEnum enumeration) where TEnum : struct
{
//You can not use a type constraints on special class Enum.
if (!typeof(TEnum).IsEnum)
throw new ArgumentException("TEnum must be of type System.Enum");
var source = Enum.GetValues(typeof(TEnum));
var items = new Dictionary<object, string>();
foreach (var value in source)
{
FieldInfo field = value.GetType().GetField(value.ToString());
DisplayAttribute attrs = (DisplayAttribute)field.GetCustomAttributes(typeof(DisplayAttribute), false).First();
items.Add(value, attrs.GetName());
}
return new SelectList(items, Constants.PropertyKey, Constants.PropertyValue, enumeration);
}
I am calling a project (WCF, but that shouldn't matter) that consumes a IList , with MVC 3 (which really should not matter either obviously) I want to convert a single column List of strings (IList which is just a list of Countries) into a List
Hard Coded list I have done like this and they work fine:
public List<SelectListItem> mothermarriedatdelivery = new List<SelectListItem>();
mothermarriedatdelivery.Add(new SelectListItem() { Text = "Yes", Value = "1" });
However, now I am trying to convert this code:
public List<SelectListItem> BirthPlace { get; set; }
BirthPlace = new List<SelectListItem>();
GetHomeRepository repo = new GetHomeRepository();
BirthPlace = repo.GetCountries();
I need to implicitly convert from the List to SelectListItem, anyone do this? Yes.. I have search and found several examples, but none that really fit my specific need.
You can use LINQ as such:
BirthPlace = repo.GetCountries()
.Select(x => new SelectListItem { Text = x, Value = x })
.ToList();
Or I think you can just use one of SelectList's constructors:
public SelectList BirthPlace { get; set; }
BirthPlace = new SelectList(repo.GetCountries());
In Controller ,
var result = proxy.GetAllLocations();
ViewBag.Area = result.Where(p => p.ParentId == null).Select(p => new SelectListItem { Text = p.LocationName, Value = p.LocationId.ToString() }).ToList();
ViewBag.Locations = result.Where(p => p.ParentId != null).Select(p => new SelectListItem { Text = p.LocationName, Value = p.LocationId.ToString() }).ToList();
return View();
In View ,
#Html.DropDownList("LocationName", ViewData["Area"] as IEnumerable<SelectListItem>)
Hi so I'm pretty new to MVC3 and Razor and I've been trying to get my head around it the past few days. I've been given a task by my project architect to create a helper method that sorts a drop down list in an MVC View. I have a View that retrieves various data from a Controller and I'm returning some values that I want to appear in a drop down list. I've been told not to sort it in the Controller and also to pass the field that we want to sort by into the helper method. I could do it like below but the architect wants to keep the view free of c sharp code:
#Html.DropDownListFor(model => model.StudyName, new SelectList(ViewBag.StudyTypes, "Value", "Text").OrderBy(l => l.Text))
So I've created some sample code and some extension methods to try and get it to work. My idea is to replicate the existing Html.DropDownList method and allow the passing of 'object htmlAttributes' so I can set the style as part of the method call.
Here's my code so far. I'm returning the data for the drop down in ViewBag.StudyTypes in the Edit Controller method:
public ActionResult Edit(int id)
{
IEnumerable<SelectListItem> mySelectList = new List<SelectListItem>();
IList<SelectListItem> myList = new List<SelectListItem>();
for (int i = 0; i < 5; i++)
{
myList.Add(new SelectListItem()
{ Value = i.ToString(), Text = "My Item " + i.ToString(), Selected = i == 2 }
);
}
mySelectList = myList;
ViewBag.StudyTypes = mySelectList;
StudyDefinition studydefinition = db.StudyDefinitions.Find(id);
return View(studydefinition);
}
Here's my View code:
#model MyStudyWeb.Models.StudyDefinition
#using MyStudyWeb.Helpers
#{
ViewBag.Mode = "Edit";
}
<div>
#Html.DropDownListSorted(new SelectList(ViewBag.StudyTypes, "Value", "Text"))<br />
#Html.DropDownListSorted("MyList", new SelectList(ViewBag.StudyTypes, "Value", "Text"))<br />
</div>
Finally below are the extension methods I'm trying to get to work. The first extension method does nothing, I just get a blank space at that point in the View. The second method kind of works but it's ugly. For the 3rd method I don't know how to specify an 'order by' parameter as the OrderBy on an IEnumerable expects a Linq expression.
namespace StudyDefinition.Helpers
{
public static class HtmlHelperExtensions
{
// 1st sort method: sort the passed in list and return a new sorted list
public static SelectList DropDownListSorted(this HtmlHelper helper, IEnumerable<SelectListItem> selectList)
{
var x = new SelectList(selectList.ToList()).OrderBy(l => l.Text);
return x as SelectList;
}
// 2nd sort method: return IHtml string and create <select> list manually
public static IHtmlString DropDownListSorted(this HtmlHelper helper, string name, SelectList selectList)
{
StringBuilder output = new StringBuilder();
(selectList).OrderBy(l => l.Text);
output.Append("<select id=" + name + " name=" + name + ">");
foreach (var item in selectList)
{
output.Append("<option value=" + item.Value.ToString() + ">" + item.Text + "</option>");
}
output.Append("</select>");
return MvcHtmlString.Create(output.ToString());
}
// 3rd sort method: pass in order by parameter - how do I use this?
public static IHtmlString DropDownListSorted(this HtmlHelper helper, string name, SelectList selectList, string orderBy)
{
StringBuilder output = new StringBuilder();
//How do I use the orderBy parameter?
(selectList).OrderBy(l => l.Text);
output.Append("<select id=" + name + " name=" + name + ">");
foreach (var item in selectList)
{
output.Append("<option value=" + item.Value.ToString() + ">" + item.Text + "</option>");
}
output.Append("</select>");
return MvcHtmlString.Create(output.ToString());
}
}
}
I really don't know the best approach to take, there may be a much simpler way that I'm totally missing and I might be at the point where I can't see the wood for the trees anymore. Some questions
Should I return a SelectList or an MvcHtmlString, or something else entirely?
For the first extension method how do I get the returned SelectList to render in the View?
How to I pass in a parameter to my extension methods that specifies the sort order?
How do I pass an 'object htmlAttributes' parameter, and how do I apply this object / parameter to the SelectList?
If anyone has some ideas or suggestions then I'd appreciate some feedback :)
The first and most important part of your code would be to get rid of any ViewBag/ViewData (which I personally consider as cancer for MVC applications) and use view models and strongly typed views.
So let's start by defining a view model which would represent the data our view will be working with (a dropdownlistg in this example):
public class MyViewModel
{
public string SelectedItem { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
}
then we could have a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
// I am explicitly putting some items out of order
Items = new[]
{
new SelectListItem { Value = "5", Text = "Item 5" },
new SelectListItem { Value = "1", Text = "Item 1" },
new SelectListItem { Value = "3", Text = "Item 3" },
new SelectListItem { Value = "4", Text = "Item 4" },
}
};
return View(model);
}
}
and a view:
#model MyViewModel
#Html.DropDownListForSorted(
x => x.SelectedItem,
Model.Items,
new { #class = "foo" }
)
and finally the last piece is the helper method which will sort the dropdown by value (you could adapt it to sort by text):
public static class HtmlExtensions
{
public static IHtmlString DropDownListForSorted<TModel, TProperty>(
this HtmlHelper<TModel> helper,
Expression<Func<TModel, TProperty>> expression,
IEnumerable<SelectListItem> items,
object htmlAttributes
)
{
var model = helper.ViewData.Model;
var orderedItems = items.OrderBy(x => x.Value);
return helper.DropDownListFor(
expression,
new SelectList(orderedItems, "Value", "Text"),
htmlAttributes
);
}
}
Just add in the sorting before you return the items to the dropdown list.
Do this:
Models: StudyViewModel.cs
public class StudyViewModel {
public string StudyName { get; set; }
public string StudyTypes { get; set; }
}
Controller: StudyController.cs
using System.Web.Mvc;
public class StudyController
{
public List<SelectListItem> studyTypes()
{
List<SelectListItem> itemList = new List<SelectListItem>();
for (var i=0; i<5; i++)
{
itemList.Add = new SelectListItem({
Value = i.ToString();
Text = "My Item";
});
}
// You can sort here....
List<SelectListItem> sortedList = itemList.OrderBy(x=>x.Text);
return sortedList;
}
public ActionResult Edit(int id)
{
//You won't need this because you get it using your
//controller's routine, instead
//ViewBag.StudyTypes = studySlots.OrderBy(e => e.Value);
//-- unless you need to add these values to the model for
// some reason (outside of filling the ddl), in which case....
// StudyViewModel svm = new StudyViewModel();
// svm.StudyTypes = studySlots.OrderBy(e => e.Value);
// svm.StudyName = "My Item";
// return View(svm);
// Otherwise, just....
return View();
}
}
View: Edit.cshtml
#Html.DropDownListFor(model => model.StudyName)
.OptionLabel('Select...')
.DataTextField('Text')
.DataValueField('Value')
.Datasource(source =>
{
// This is where you populate your data from the controller
source.Read(read =>
{
read.Action("studyTypes", "Study");
});
})
.Value(Model.StudyName != null ? Model.StudyName.ToString() : "")
)
This way will avoid ViewBags and just use a function to fill in the values, directly.
If you are using a database you can use a query to define the sort element
using (BDMMContext dataContext = new BDMMContext())
{
foreach (Arquiteto arq in dataContext.Arquitetos.SqlQuery("SELECT * FROM Arquitetos ORDER BY Nome"))
{
SelectListItem selectItem = new SelectListItem { Text = arq.Nome, Value = arq.Arquiteto_Id.ToString() };
//
list.Add(selectItem);
}
}
If you have a simple Linq query like:
var result = from record in db.Customer
select new { Text = record.Name,
Value = record.ID.ToString() };
which is returning an object that can be mapped to a Drop Down List, is it possible to dynamically specify which fields map to Text and Value?
Of course, you could do a big case (switch) statement, then code each Linq query separately but this isn't very elegant. What would be nice would be something like:
(pseudo code)
var myTextField = db.Customer["Name"]; // Could be an enumeration??
var myValueField = db.Customer["ID"]; // Idea: choose the field outside the query
var result = from record in db.Customer
select new { Text = myTextField,
Value = myValueField };
Right way to do this is with closures.
Func<Customer, string> myTextField = (Customer c) => c["Name"];
Func<Customer, int> myValueField = (Customer c) => c["ID"];
var result = from record in db.Customer
select new { Text = myTextField(record),
Value = myValueField(record) };
The one limitation is that your definition of myTextField always needs to return a string.
You could try something like
class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
var dict = new Dictionary<string, Func<Customer, string>>
{ { "ID", (Customer c) => c.ID.ToString() },
{ "Name", (Customer c) => c.Name},
{ "Surname", (Customer c) => c.Surname } };
List<Customer> rows = new List<Customer>();
rows.Add(new Customer { ID = 1, Name = "Foo", Surname = "Bar"});
var list = from r in rows
select new { Text = dict["ID"](r), Value = dict["Name"](r) };
To try to access the properties dynamically, you could try something like
var dict = new Dictionary<string, Func<Customer, string>>
{ { "ID", (Customer c) => c.GetType().GetProperty("ID").GetValue(c,null).ToString() },
{ "Name", (Customer c) => c.GetType().GetProperty("Name").GetValue(c,null).ToString()},
{ "Surname", (Customer c) => c.GetType().GetProperty("Surname").GetValue(c,null).ToString() } };