I am working on a membership app created in MVC3. I have two different kinds of members Organisation and Individual. After they paying the membership fee, I need to track their payment history. Thus, in the first row (the field after text Member), I need to display the "OrganisationName" of Organisation and "MemberForname" of Individual in DropDownList. But now I can only display either "OrganisationName" or "MemberForname". I tried a lot, but still can't figure it out by displaying both. Any ideas? Thanks in advance.[The screen shot above only displays "OrganisationName", and the bottom one only displays "MemberForname"].
<td>
Member
</td>
<td>
#Html.DropDownList("member", ((IEnumerable<ProActiveMembership.Areas.Members.Models.Member>)ViewBag.PossibleMembers).Select(option => new SelectListItem
{
Text = Html.DisplayTextFor(_ => option.Forename).ToString(),
//Text = Html.DisplayTextFor(_ => option.OrganisationName).ToString(),
Value = option.MemberID.ToString(),
Selected = (Model != null) && (option.MemberID == Model.MemberID)
}), "Choose...", new { id = "ddl" })
#Html.ValidationMessageFor(model => model.MemberID)
</td>
You can set the Text property like this: Text = string.Format("{0} {1}", option.Forename, option.OrganisationName)
Your code would then look like this:
<td>
Member
</td>
<td>
#Html.DropDownList("member", ((IEnumerable<ProActiveMembership.Areas.Members.Models.Member>)ViewBag.PossibleMembers).Select(option => new SelectListItem
{
Text = string.Format("{0} {1}", option.Forename, option.OrganisationName),
Value = option.MemberID.ToString(),
Selected = (Model != null) && (option.MemberID == Model.MemberID)
}), "Choose...", new { id = "ddl" })
#Html.ValidationMessageFor(model => model.MemberID)
</td>
As andreister suggests you can also add a member to ProActiveMembership.Areas.Members.Models.Member that returns the full name. Something like this:
public string FullName { get { return string.Format("{0} {1}", Forename, OrganisationName); } }
You can then use the new member like this:
Text = option.FullName
Related
I have a #foreach in my View that makes a table. Each row has two items within it's td. When I click my Edit button, the visible item's in a row disappear (DislayFor's) and the hidden items in the row appear (DropDownList)
View Code
<td class="col-md-3">
<span class="item-display">
<span style="font-size: 17px">
#Html.DisplayFor(modelItem => item.Movie.Name)
</span>
</span>
<span class="item-field">
#Html.DropDownList("movieID", item.Movie.Name)
</span>
</td>
By doing this I can select a new value in the DropDownList and then Save that change to my Database (then hiding the DropDownList and unhiding the DisplayFor.
Everything works fine, however I have an issue with the initally selected value, it appears twice with the initial value having an actual value of 0 (which relates to nothing in the DB).
Picture Example
QUESTION:
Right now my dropdown add's a value upon clicking Edit, the item initially selected has the correct name but it is given the index of 0 (which is invalid for my database).
I want to have the initially selected item to NOT be added, but rather to set the selector of the dropdown to the CORRECT INDEX of the appropriate item. I am not sure why it duplicates my selected item twice.
Controller Code
public ActionResult Index(string Filter, string searchString)
{
if (String.IsNullOrEmpty(searchString) || String.IsNullOrEmpty(Filter) || (Int32.Parse(Filter) == 0))
{
ViewBag.employeeID = new SelectList(db.Employees, "ID", "Name", );
ViewBag.movieID = new SelectList(db.Movies, "ID", "Name", initiallySelectedValue);
ViewBag.roleID = new SelectList(db.Roles, "ID", "RoleType");
var movieemployees = db.MovieEmployees.Include(m => m.Employee).Include(m => m.Movie).Include(m => m.Role);
return View(movieemployees.ToList().OrderBy(x => x.Employee.Name));
}
else
{
ViewBag.employeeID = new SelectList(db.Employees, "ID", "Name");
ViewBag.movieID = new SelectList(db.Movies, "ID", "Name");
ViewBag.roleID = new SelectList(db.Roles, "ID", "RoleType");
var parameter = Int32.Parse(Filter);
return View(db.MovieEmployees.Include(m => m.Employee).Include(m => m.Movie).Include(m => m.Role).Where(x => (parameter == 1 && x.Movie.Name.Contains(searchString)) || (parameter == 2 && x.Employee.Name.Contains(searchString)) || (parameter == 3 && x.Role.RoleType.Contains(searchString))).Distinct().ToList().OrderBy(x => x.Employee.Name));
}
}
Your understanding of the parameters for DropDownList isn't quite correct, but you're close! The second parameter for DropDownList (in your case item.Movie.Name) is adding an option label. If you replaced that with a hard-coded string that would serve as a good example of what it's doing (you would see that string as the first option of every select input).
It sounds to me like you want to delete that last parameter since it will only end up serving as a duplicate. Your code would simply look like this:
#Html.DropDownList("movieID")
The important part of your code is where you're building the object that you're storing in ViewData with the key movieID. You didn't post your controller code, but I imagine it looks something like:
var movies = movieRepository.GetAllMovies();
ViewData["movieID"] = new SelectList(movies, "Name", "Id", initiallySelectedValue);
Where Name and Id are the names of properties on the movie object and initiallySelectedValue is rather self explanatory.
Edit
Here is an example of how I would go about solving your problem:
Controller
public ActionResult Index() {
//Get all the possible movies that can be selected
var movies = movieRepository.GetAllMovies();
//Get a list of employees with their related favorite movie record
var employeesWithFavoriteMovie = movieRepository.GetEmployeesWithMovie();
var employeeModels = new List<EmployeeModel>();
//Iterate through the list of employees and their favorite movie, and build the model
foreach (var employeeWithFavoriteMovie in employeesWithFavoriteMovie) {
employeeModels.Add(new EmployeeModel() {
FirstName = employeeWithFavoriteMovie.FirstName,
FavoriteMovieId = employeeWithFavoriteMovie.Movie.Id,
MovieSelectList = new SelectList(movies, "Name", "Id", employeeWithFavoriteMovie.Movie.Id)
});
}
return View(employeeModels);
}
View
#model IEnumerable<WebApplication1.Controllers.EmployeeModel>
#foreach (var employeeModel in Model) {
#Html.DropDownList("Test", employeeModel.MovieSelectList)
}
Notice how a SelectList was built for each employee and that each list is then populated with that employees current favorite movie id. This will now put you in a position to have a properly built SelectList for each employee.
#Html.DropDownListFor(model => model.classmasterd_HCF[i].TD_TEACHER, new SelectList(Model.Teacher, "ParamKey", "ParamValue", Model.classmasterd_HCF[i].TD_TEACHER) as SelectList, new { #class = "form-control input-sm DtlField EditableCtrl", #style = "min-width:100%;", #disabled = "disabled" })
where Teacher in Model.Teacher is a model with code in paramKey and description in paramvalue. Selected value saved in TD_TEACHER field
I need to access practiceid property in my controller file please help how I can access this
Corporate
Tax & Employee Comp/Exec Benefits
Business Finance & Restructuring
Regulatory
My csHtml code is as follows:
#foreach (var facetData in Model.SearchResultItems.Facets.Select((x) => new { Item = x.Key, Index = x.Value }))
{
<tr>
<td>
#Html.ActionLink(#facetData.Index, "Search","Search", new { practiceid = #facetData.Item })
</td>
</tr>
}
and controller code is as follows:
public ActionResult Search(string practiceid)
{
}
But I'm not getting anything in my practiceid parameter.
See this question.
What you want to do is to add parameters to the tag, not to the link. Which means you should leave fourth argument null and use fifth instead. ie.
#Html.ActionLink(#facetData.Index, "Search","Search", null, new { practiceid = facetData.Item })
And the documentation for this helper method with focus on fifth parameter.
Add the extra null
#foreach (var facetData in Model.SearchResultItems.Facets.Select((x) => new { Item = x.Key, Index = x.Value }))
{
<tr>
<td>
#Html.ActionLink(#facetData.Index, "Search","Search", new { practiceid = facetData.Item }, null)
</td>
</tr>
}
I am updating product Quantity by Update button, after clicking on update button page is reloading, instead of reloading that page i want to update that "cartUpdatePanel" table area only by Ajax
My View is
using (Html.BeginRouteForm("ShoppingCart", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<table id="cartUpdatePanel" class="table_class" cellpadding="0" cellspacing="0">
#foreach (var item in Model.Items)
{
<tr style="background: #f3f3f3;">
<td>
<input type="submit" name="updatecartproduct#(item.Id)" value="Update Cart" id="updatecartproduct#(item.Id)" />
</td>
</tr>
}
}
My Controller action is, by which i am updating Product Quantity
[ValidateInput(false)]
[HttpPost, ActionName("Cart")]
[FormValueRequired(FormValueRequirement.StartsWith, "updatecartproduct")]
public ActionResult UpdateCartProduct(FormCollection form)
{
if (!_permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart))
return RedirectToRoute("HomePage");
//get shopping cart item identifier
int sciId = 0;
foreach (var formValue in form.AllKeys)
if (formValue.StartsWith("updatecartproduct", StringComparison.InvariantCultureIgnoreCase))
{
sciId = Convert.ToInt32(formValue.Substring("updatecartproduct".Length));
break;
}
//get shopping cart item
var cart = _workContext.CurrentCustomer.ShoppingCartItems
.Where(x => x.ShoppingCartType == ShoppingCartType.ShoppingCart).ToList();
var sci = cart.Where(x => x.Id == sciId).FirstOrDefault();
if (sci == null)
{
return RedirectToRoute("ShoppingCart");
}
//update the cart item
var warnings = new List<string>();
foreach (string formKey in form.AllKeys)
if (formKey.Equals(string.Format("itemquantity{0}", sci.Id), StringComparison.InvariantCultureIgnoreCase))
{
int newQuantity = sci.Quantity;
if (int.TryParse(form[formKey], out newQuantity))
{
warnings.AddRange(_shoppingCartService.UpdateShoppingCartItem(_workContext.CurrentCustomer,
sci.Id, newQuantity, true));
}
break;
}
//updated cart
cart = _workContext.CurrentCustomer.ShoppingCartItems.Where(x => x.ShoppingCartType == ShoppingCartType.ShoppingCart).ToList();
var model = PrepareShoppingCartModel(new ShoppingCartModel(), cart, true, false, true);
//update current warnings
//find model
var sciModel = model.Items.Where(x => x.Id == sciId).FirstOrDefault();
if (sciModel != null)
foreach (var w in warnings)
if (!sciModel.Warnings.Contains(w))
sciModel.Warnings.Add(w);
return View(model);
}
How i will achieve to update "cartUpdatePanel" table area after clicking on update button by ajax
Thanx in Advance
Please consider using Ajax.BeginForm helper to create the form. You can use AjaxOptions to specify callback code to capture server output and do whatever you want (including injecting it to a div, table, field set ..)
Using the Ajax.BeginForm is very easy
#using (Ajax.BeginForm(
"name_of_the_action",
new AjaxOptions {
OnSuccess = "processServerResp",
HttpMethod = "POST"},
new {enctype="multipart/form-data"})
){
// rest of the form code
}
Now using javascript, implement processServerResp as a function which takes a single parameter. This parameter will contain what ever values passed from the server to the client. Assuming the server is returning html, you can use the following code to inject it into a container with the id of id_fo_the_div
function processServerResp(serverData){
$(‘#id_fo_the_div’).html(serverData);
// or inject into a table ..
}
You can tap into other interesting features provided by AjaxOptions and do very interesting things.
A good article on Ahax.BeginForm http://www.blackbeltcoder.com/Articles/script/using-ajax-beginform-with-asp-net-mvc
Happy coding
I'm using ASP.NET MVC 3, and just ran into a 'gotcha' using the DropDownListFor HTML Helper.
I do this in my Controller:
ViewBag.ShippingTypes = this.SelectListDataRepository.GetShippingTypes();
And the GetShippingTypes method:
public SelectList GetShippingTypes()
{
List<ShippingTypeDto> shippingTypes = this._orderService.GetShippingTypes();
return new SelectList(shippingTypes, "Id", "Name");
}
The reason I put it in the ViewBag and not in the model (I have strongly typed models for each view), is that I have a collection of items that renders using an EditorTemplate, which also needs to access the ShippingTypes select list.
Otherwise I need to loop through the entire collection, and assign a ShippingTypes property then.
So far so good.
In my view, I do this:
#Html.DropDownListFor(m => m.RequiredShippingTypeId, ViewBag.ShippingTypes as SelectList)
(RequiredShippingTypeId is of type Int32)
What happens is, that the value of RequiredShippingTypeId is not selected in the drop down.
I came across this: http://web.archive.org/web/20090628135923/http://blog.benhartonline.com/post/2008/11/24/ASPNET-MVC-SelectList-selectedValue-Gotcha.aspx
He suggests that MVC will lookup the selected value from ViewData, when the select list is from ViewData. I'm not sure this is the case anymore, since the blog post is old and he's talking about MVC 1 beta.
A workaround that solves this issue is this:
#Html.DropDownListFor(m => m.RequiredShippingTypeId, new SelectList(ViewBag.ShippingTypes as IEnumerable<SelectListItem>, "Value", "Text", Model.RequiredShippingTypeId.ToString()))
I tried not to ToString on RequiredShippingTypeId at the end, which gives me the same behavior as before: No item selected.
I'm thinking this is a datatype issue. Ultimately, the HTML helper is comparing strings (in the Select List) with the Int32 (from the RequiredShippingTypeId).
But why does it not work when putting the SelectList in the ViewBag -- when it works perfectly when adding it to a model, and doing this inside the view:
#Html.DropDownListFor(m => m.Product.RequiredShippingTypeId, Model.ShippingTypes)
The reason why this doesn't work is because of a limitation of the DropDownListFor helper: it is able to infer the selected value using the lambda expression passed as first argument only if this lambda expression is a simple property access expression. For example this doesn't work with array indexer access expressions which is your case because of the editor template.
You basically have (excluding the editor template):
#Html.DropDownListFor(
m => m.ShippingTypes[i].RequiredShippingTypeId,
ViewBag.ShippingTypes as IEnumerable<SelectListItem>
)
The following is not supported: m => m.ShippingTypes[i].RequiredShippingTypeId. It works only with simple property access expressions but not with indexed collection access.
The workaround you have found is the correct way to solve this problem, by explicitly passing the selected value when building the SelectList.
This might be silly, but does adding it to a variable in your view do anything?
var shippingTypes = ViewBag.ShippingTypes;
#Html.DropDownListFor(m => m.Product.RequiredShippingTypeId, shippingTypes)
you can create dynamic viewdata instead of viewbag for each dropdownlist field for complex type.
hope this will give you hint how to do that
#if (Model.Exchange != null)
{
for (int i = 0; i < Model.Exchange.Count; i++)
{
<tr>
#Html.HiddenFor(model => model.Exchange[i].companyExchangeDtlsId)
<td>
#Html.DropDownListFor(model => model.Exchange[i].categoryDetailsId, ViewData["Exchange" + i] as SelectList, " Select category", new { #id = "ddlexchange", #class = "form-control custom-form-control required" })
#Html.ValidationMessageFor(model => model.Exchange[i].categoryDetailsId, "", new { #class = "text-danger" })
</td>
<td>
#Html.TextAreaFor(model => model.Exchange[i].Address, new { #class = "form-control custom-form-control", #style = "margin:5px;display:inline" })
#Html.ValidationMessageFor(model => model.Exchange[i].Address, "", new { #class = "text-danger" })
</td>
</tr>
}
}
ViewModel CompanyDetail = companyDetailService.GetCompanyDetails(id);
if (CompanyDetail.Exchange != null)
for (int i = 0; i < CompanyDetail.Exchange.Count; i++)
{
ViewData["Exchange" + i]= new SelectList(companyDetailService.GetComapnyExchange(), "categoryDetailsId", "LOV", CompanyDetail.Exchange[i].categoryDetailsId);
}
I was just hit by this limitation and figured out a simple workaround. Just defined extension method that internally generates SelectList with correct selected item.
public static class HtmlHelperExtensions
{
public static MvcHtmlString DropDownListForEx<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
IEnumerable<SelectListItem> selectList,
object htmlAttributes = null)
{
var selectedValue = expression.Compile().Invoke(htmlHelper.ViewData.Model);
var selectListCopy = new SelectList(selectList.ToList(), nameof(SelectListItem.Value), nameof(SelectListItem.Text), selectedValue);
return htmlHelper.DropDownListFor(expression, selectListCopy, htmlAttributes);
}
}
The best thing is that this extension can be used the same way as original DropDownListFor:
#for(var i = 0; i < Model.Items.Count(); i++)
{
#Html.DropDownListForEx(x => x.Items[i].CountryId, Model.AllCountries)
}
There is an overloaded method for #html.DropdownList for to handle this.
There is an alternative to set the selected value on the HTML Dropdown List.
#Html.DropDownListFor(m => m.Section[b].State,
new SelectList(Model.StatesDropdown, "value", "text", Model.Section[b].State))
I was able to get the selected value from the model.
"value", "text", Model.Section[b].State this section the above syntax adds the selected attribute to the value loaded from the Controller
I'm trying to list two radio buttons in each row of a table, but I haven't been able to assign unique IDs to each radio button. I'd like to assign the IDs based on the #item.myID as follows:
#foreach (var item in Model)
{
<tr>
<td>
#Html.RadioButton("Yes", #item.myID, #item.IsCool, new { id = "#item.myID", autopostback = "true" })
#Html.RadioButton("No", #item.myID, !#item.IsCool, new { id = "#item.myID", autopostback = "true" })
</td>
</tr>
}
However, the IDs keep rendering literally as "#item.myID". In other words, it's not treating the # sign as a special character. I've also tried using parenthesis, like this: "#(item.myID)".
You need to remove the quotes from around the id assignment, like so;
#foreach (var item in Model)
{
<tr>
<td>
#Html.RadioButton("Yes", item.myID, item.IsCool, new { id = item.myID, autopostback = "true" })
#Html.RadioButton("No", item.myID, !item.IsCool, new { id = item.myID, autopostback = "true" })
</td>
</tr>
}
Also, note that you don't need the additional "#" symbol when you are already in the context of another Razor code block - the Razor View Engine is pretty clever :)