So I have a area setup (Admin). In the Admin Area I have a _ViewStart.cshtml file which links to a Shared/_Layout.cshtml file.
What I need is for the layout file to get some data passed to it (like a model). There will be a drop down at the top right of the page which is common accross all pages in the admin area. It wouldn't be used in any other areas or the root of the application, only in this area.
Is there a way to assign a common controller to a layout or is Partial the way forward with this?
You could use child actions. You could define a model:
public class MyViewModel
{
public string SelectedId { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
}
then have a controller:
public class ItemsController: Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
Items = new[]
{
new SelectListItem { Value = "1", Text = "item 1" },
new SelectListItem { Value = "2", Text = "item 2" },
new SelectListItem { Value = "3", Text = "item 3" },
}
};
return PartialView(model);
}
}
and then a corresponding partial (~/Areas/Admins/Views/Items/Index.cshtml):
#model MyViewModel
#Html.DropDownListFor(x => x.SelectedId, Model.Items)
Now, inside the layout of your are you could render this action:
#Html.Action("Index", "Items", new { area = "admin" })
Related
This is done by adding a view from my controller and selecting my dto as template
My DTO
public class Company_DTO
{
public long ID_Company { get; set; }
public string ESTATE_Company { get; set; }
}
MyController
public ActionResult UpdateCompany()
{
ViewBag.ListOfCompanies = DependencyFactory.Resolve<ICompanyBusiness>().GetCompany(); // this return a List<int> and following what I read for viewbag this should be right.
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UpdateCompany([Bind]Company_DTO company_DTO)
{
try
{
//code
}
catch
{
return View();
}
}
View
<div class="form-group">
#Html.DropDownListFor(model => model.ID_Company , ViewBag.ListOfCompanies) // Here I get an error on my #Html that my dto does nothave a list.
</div>
I want the selected item to be ID_Company, but here it seems to be trying to add the whole list when I just want the selected item, I cant find any documentation or question that can solve my issue.
I Cant EDIT the DTO.
Thanks for any help and hope I am being clear enough.
This should solve your problem:
View
<div class="form-group">
#Html.DropDownListFor(model => model.ID_Company, new SelectList(ViewBag.Accounts, "ID_Company", "ESTATE_Company"))
</div>
Supposing your view is strongly typed (#model Company_DTO).
Hope this helps
consider the following example:
public class HomeController : Controller
{
private List<SelectListItem> items = new List<SelectListItem>()
{
new SelectListItem() { Text = "Zero", Value = "0"},
new SelectListItem() { Text = "One", Value = "1"},
new SelectListItem() { Text = "Two", Value = "2"}
};
public ActionResult Index()
{
ViewBag.Items = items;
return View(new Boo() { Id = 1, Name = "Boo name"});
}
}
public class Boo
{
public int Id { get; set; }
public string Name { get; set; }
}
the view:
#model WebApi.Controllers.Boo
#Html.DropDownListFor(x=>x.Id, (IEnumerable<SelectListItem>) ViewBag.Items)
so, ViewBag.ListOfCompanies should contain IEnumerable. Each SelectListItem has Text and Value property , you need to assign ESTATE_Company and ID_Company respectively. something like this:
var companiesList = //get companies list
ViewBag.ListOfCompanies = companiesList.Select(x => new SelectListItem() {Text = x.ESTATE_Company, Value = x.ID_Company.ToString()});
....
#Html.DropDownListFor(x=>x.ID_Company, ViewBag.Items as IEnumerable<SelectListItem>)
When I run the code, I can only select one item at a time, that's weird because 'ListBoxFor()' is used to select multiple items, so what i want is:
Select multiple items
View (Index.cshtml):
<div>
#Html.ListBoxFor(m => m.DropDownItems, new MultiSelectList(Repository.DDFetchItems(), "Value", "Text", Model.DropDownItems))
</div>
Model (ModelVariables.cs):
public class ModelVariables
{
public List<SelectListItem> DropDownItems { get; set; }
}
public static class Repository
{
public static List<SelectListItem> DDFetchItems()
{
return new List<SelectListItem>()
{
new SelectListItem(){ Text = "Dogs", Value = "1", Selected = true},
new SelectListItem(){ Text = "Cats", Value = "2"},
new SelectListItem(){ Text = "Death", Value = "3"}
};
}
}
Controller (HomeController.cs):
[HttpGet]
public ActionResult Index()
{
ModelVariables model = new ModelVariables()
{
DropDownItems = Repository.DDFetchItems()
};
return View(model);
}
You cannot bind a <select multiple> to a collection of complex objects (which is what List<SelectListItem> is). A <select multiple> posts back an array of simple values (in your case, if you select the 1st and 3rd options, it will submit [1, 3] (the values of the selected options).
Your model needs a IEnumerable<int> property to bind to.
public class ModelVariables
{
public IEnumerable<int> SelectedItems { get; set; }
public IEnumerable<SelectListItem> DropDownItems { get; set; }
}
and then in the GET method
public ActionResult Index()
{
var ModelVariables= new ModelVariables()
{
DropDownItems = Repository.DDFetchItems(),
SelectedItems = new List<int>(){ 1, 3 } // to preselect the 1st and 3rd options
};
return View(model);
}
and in the view
#Html.ListBoxFor(m => m.SelectedItems, Model.DropDownItems)
Side notes
Remove Selected = true in the DDFetchItems() method - its
ignored by the ListBoxFor() method because its the value of the
property your binding to which determines what is selected
There is not need to build a new identical SelectList from the
first one inside the ListBoxFor() method (property DropDownItems
is already IEumerable<SelectListItem>)
I got two ways to bind my list of values to a dropdown in MVC3. But not sure which is the difference and the best/simpler way to bind.
//Code
public List<SelectListItem> CountryList
{
get
{
return new List<SelectListItem>
{
new SelectListItem { Value = "1", Text = "Bangladesh" },
new SelectListItem { Value = "2", Text = "India" },
new SelectListItem { Value = "3", Text = "Nepal" },
new SelectListItem { Value = "4", Text = "SriLanka" },
};
}
}
(Or)
public SelectList StatusList()
{
List<SelectListItem> lstStatus = new List<SelectListItem>
{
new SelectListItem { Value = "1", Text = "Yes" },
new SelectListItem { Value = "2", Text = "No" },
};
return new SelectList(lstStatus, "Value", "Text", Status);
}
Do i have any advantages/disadvantages in one over another. I have to bind these values and get/set the selected value. Which method will be best one go with?
Kindly suggest.
I tend to use a generic enumeration of SelectListItem in MVC applications. The main reason is that makes more sense when you use ViewModels with your views.
Let's say I have movies stored in a database. I represent a movie with a POCO class.
public class Movie
{
public string Genre { get; set; }
}
The page to edit the movie receive a ViewModel.
public class MovieViewModel
{
public string Genre { get; set; }
public IEnumerable<SelectListItem> GenreList
{
get
{
yield return new SelectListItem { Text = "Comedy", Value = "1" };
yield return new SelectListItem { Text = "Drama", Value = "2" };
yield return new SelectListItem { Text = "Documentary", Value = "3" };
}
}
}
The ViewModel is my model but with additional properties to personalize my view, like the list of the available genres.
Finally in my view, I populate my dropdownlist using the ASP.NET wrapper Html.DropDownListFor().
#model MvcApplication1.Models.MovieViewModel
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
</head>
<body>
<div>
#Html.DropDownListFor(m => m.Genre, Model.GenreList)
</div>
</body>
</html>
The selected value is then automatically chosen using the ViewModel.
#Html.DropDownListFor(m => m.branch, CommonMethod.getBranch("",Model.branch), "--Select--", new { #multiple = "multiple" })
#Html.DropDownListFor(m => m.division, CommonMethod.getDivision(Model.branch,Model.division), "--Select--", new { #multiple = "multiple" })
I have two instances of DropDownListFor. I want to set selected as true for those which have previously stored values for Model.branch and Model.division. These are string arrays of stored ids
class CommonMethod
{
public static List<SelectListItem> getDivision(string [] branchid , string [] selected)
{
DBEntities db = new DBEntities();
List<SelectListItem> division = new List<SelectListItem>();
foreach (var b in branchid)
{
var bid = Convert.ToByte(b);
var div = (from d in db.Divisions where d.BranchID == bid select d).ToList();
foreach (var d in div)
{
division.Add(new SelectListItem { Selected = selected.Contains(d.DivisionID.ToString()), Text = d.Description, Value = d.DivisionID.ToString() });
}
}
}
return division;
}
}
The returned value of division is selected as true for the selected item in the model, but on view side it is not selected.
Use a ListBoxFor instead of DropDownListFor:
#Html.ListBoxFor(m => m.branch, CommonMethod.getBranch("", Model.branch), "--Select--")
#Html.ListBoxFor(m => m.division, CommonMethod.getDivision(Model.branch, Model.division), "--Select--")
The branch and division properties must obviously be collections that will contain the selected values.
And a full example of the proper way to build a multiple select dropdown using a view model:
public class MyViewModel
{
public int[] SelectedValues { get; set; }
public IEnumerable<SelectListItem> Values { get; set; }
}
that would be populated in the controller:
public ActionResult Index()
{
var model = new MyViewModel();
// preselect items with values 2 and 4
model.SelectedValues = new[] { 2, 4 };
// the list of available values
model.Values = new[]
{
new SelectListItem { Value = "1", Text = "item 1" },
new SelectListItem { Value = "2", Text = "item 2" },
new SelectListItem { Value = "3", Text = "item 3" },
new SelectListItem { Value = "4", Text = "item 4" },
};
return View(model);
}
and in the view:
#model MyViewModel
...
#Html.ListBoxFor(x => x.SelectedValues, Model.Values)
It is the HTML helper that will automatically preselect the items whose values match those of the SelectedValues property.
For me it works also for #Html.DropDownListFor:
Model:
public class MyViewModel
{
public int[] SelectedValues { get; set; }
public IEnumerable<SelectListItem> Values { get; set; }
}
Controller:
public ActionResult Index()
{
var model = new MyViewModel();
// the list of available values
model.Values = new[]
{
new SelectListItem { Value = "2", Text = "2", Selected = true },
new SelectListItem { Value = "3", Text = "3", Selected = true },
new SelectListItem { Value = "6", Text = "6", Selected = true }
};
return View(model);
}
Razor:
#Html.DropDownListFor(m => m.SelectedValues, Model.Values, new { multiple = "true" })
Submitted SelectedValues in controller looks like:
Though quite old thread but posting this answer after following other answers here, which unfortunately didn't work for me. So, for those who might have stumbled here recently or in near future, Below is what has worked for me.
This is what helped me
The catch for me was MultiSelectList class and I was using SelectList.
Don't know situation in 2012 or 2015. but, now both these helper methods #Html.DropDownListFor and #Html.ListBoxFor helper methods accept IEnumerable<SelectListItem> so you can not pass any random IEnumerable object and expect these helper methods to do the job.
These helper methods now also accept the object of SelectList and MultiSelectList classes in which you can pass the selected values directly while creating there objects.
For example see below code how i created my multi select drop down list.
#Html.DropDownListFor(model => #Model.arrSelectUsers, new MultiSelectList(Model.ListofUsersDTO, "Value", "Text", #Model.arrSelectUsers),
new
{
id = "_ddlUserList",
#class = "form-control multiselect-dropdown",
multiple = "true",
data_placeholder = "Select Users"
})
I have a page that has two drop down lists and based upon the selection of these two lists I would like to populate a textarea with some data on submit button press.
The behavior that I am seeing while debugging is that the page is rendered, I make my selections and press submit. The DataAccess returns the correct results and the View returns, but with an exception "There is no ViewData item of type 'IEnumerable' that has the key 'People'.
I can see that I could re-setup the drop down lists, but it feels like I'm approaching this incorrectly. Is there another approach for doing this sort of action in MVC 3?
public ActionResult Test()
{
//People for dropdownlist 1
var db = peopleRepository.People;
var query = db.Select(c => new {c.Id, c.Name});
ViewBag.People = new SelectList(query.AsEnumerable(), "Id", "Name");
//Elements for dropdownlist 2
var list = new Dictionary<string, string> {{"1", "Name"}, {"2", "Address"}, {"3", "Zip"}};
ViewBag.Elements = new SelectList(list, "Key", "Value");
return View();
}
// This part is what I'm confused about.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Test(string people, string elements)
{
if (ModelState.IsValid)
{
// Output from persistent storage query
var da = new DatabaseAccess(people, elements);
ViewBag.Results = da.Execute();
}
return View();
}
View:
#using (Html.BeginForm("Test", "Home", FormMethod.Post))
{
#Html.DropDownList("People", (SelectList)ViewBag.People, "--Select One--")
#Html.DropDownList("Elements", (SelectList)ViewBag.Elements, "--Select One--")
#Html.TextArea("Results", (string)ViewBag.Results, 10, 120, "")
}
Here is how I would quickly construct it :
Model :
public class People
{
public int Id { get; set; }
public string Name { get; set; }
}
ViewModel (everything needed by the view):
public class TestViewModel
{
public int SelectedPeopleId { get; set; }
public string SelectedElementId { get; set; }
public SelectList People { get; set; }
public SelectList Elements { get; set; }
public String Results { get; set; }
}
Controller (used Index as the default Action, create an init function for the view model that can be adapted)to anything more appropriate :
public class HomeController : Controller
{
private static TestViewModel InitTestVM()
{
//People for dropdownlist 1
var db = new List<People>();//peopleRepository.People;
db.Add(new People { Id = 1, Name = "Name 1" });
db.Add(new People { Id = 2, Name = "Name 2" });
var query = db.Select(c => new { c.Id, c.Name });
//Elements for dropdownlist 2
var list = new Dictionary<string, string> { { "1", "Name" }, { "2", "Address" }, { "3", "Zip" } };
TestViewModel testVM = new TestViewModel
{
People = new SelectList(query.AsEnumerable(), "Id", "Name"),
Elements = new SelectList(list, "Key", "Value")
};
return testVM;
}
public ActionResult Index()
{
return View(InitTestVM());
}
// This part is what I'm confused about.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(TestViewModel testVM)
{
var vm = InitTestVM();
if (ModelState.IsValid && testVM != null)
{
ModelState.Clear();
// Output from persistent storage query
//var da = new DatabaseAccess(people, elements);
vm.Results = "sfdfsdfsdfsdfsdfsdfsdfsdf";//da.Execute();
vm.SelectedElementId = testVM.SelectedElementId;
vm.SelectedPeopleId = testVM.SelectedPeopleId;
return View(vm);
}
return View(vm);
}
}
And finally the View :
#model ViewModels.TestViewModel
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
#Html.DropDownListFor(m => m.SelectedPeopleId, Model.People, "--Select One--")
#Html.DropDownListFor(m => m.SelectedElementId, Model.Elements, "--Select One--")
#Html.TextAreaFor(m => m.Results, 10, 120, "")
<input type="submit" value="Test" />
}