AutoMapper map Enum to SelectList - Selected value not working - c#

I have created a map which convert an enum to a SelectList by using a custom implementation of ITypeConverter.
public class DeliveryModeToSelectListTypeConverter : ITypeConverter<ProductDeliveryMode, SelectList>
{
public SelectList Convert( ResolutionContext context ) {
ProductDeliveryMode pdm = (ProductDeliveryMode)context.SourceValue;
List<SelectListItem> items = new List<SelectListItem>();
SelectListItem sli1 = new SelectListItem() {
Text = StringEnum.GetStringValue( ProductDeliveryMode.DeliveryModeActivationByPin ),
Value = ( (int)ProductDeliveryMode.DeliveryModeActivationByPin ).ToString(),
Selected = (pdm == ProductDeliveryMode.DeliveryModeActivationByPin)
};
items.Add( sli1 );
[...other enum members here...]
SelectList sl = new SelectList( items, "Value", "Text", pdm );
return sl;
}
}
And then I have created a Map by using
Mapper.CreateMap<ProductDeliveryMode, SelectList>()
.ConvertUsing( new DeliveryModeToSelectListTypeConverter() );
Mapper.CreateMap<Product, ProductViewModel>()
.ForMember( p => p.DeliveryModeOptions, opt => opt.MapFrom( x => x.DeliveryMode ) )
[...other members here...]
.Include<ExperienceProduct, ExperienceProductViewModel>();
Mapper.CreateMap<ExperienceProduct, ExperienceProductViewModel>()
.IncludeBase<Product, ProductViewModel>()
));
Everything seems to works very nice except from the fact that the Selected value of the SelectListItem does not maintains its value. I have been able to step into the code and the SelectListItem sli1 it's correctly created with the selected value equal to true.
However when i check that value after a mapping the value is always false as you can see from the following screenshots.
Where do I am wrong with this code?

The problem is when you create the select list:
SelectList sl = new SelectList( items, "Value", "Text", pdm);
You're passing the selected item as pdm of type ProductDeliveryMode, which is being compared against the Value property of type string.
From your comment below, the solution was to pass pdm as a string.

Related

How to keep the selected value from the dropdown when the page is changed?

I am working on a project in C# (using mvc) and I had to make a dropdown filter in my view with only two choices: Yes and No.
Here is the code that populates the dropdown:
Service method:
public List<SelectListItem> cancelledForDp()
{
List<SelectListItem> cancelled = new List<SelectListItem>();
var data = new[]
{
new SelectListItem { Value = "1",Text = "Yes" },
new SelectListItem { Value = "NULL",Text = "No" }
};
cancelled = data.ToList();
return cancelled;
}
Controller:
ViewBag.cancelledDp = utilService.cancelledForDp();
View:
#Html.DropDownList("cancelled", (IEnumerable<SelectListItem>)ViewBag.cancelledDp, new { id = "chosenCancelled" })
The values in the column in the database table are: "1" and NULL (I mean the values connected with the filter). My filter works correctly.
When I filter with the value No, a few pages are returned. When I go to a different page than the first (2 or more), the value of the dropdown is not kept. It should be No, but instead it is Yes.
I searched for answers connected with my problem here, but did not find anything appropriate.
I guessed the problem is connected with NULL value so I tried this:
In the service:
public List<SelectListItem> cancelledForDp()
{
List<SelectListItem> cancelled = new List<SelectListItem>();
var data = new[]
{
new SelectListItem { Value = "1",Text = "Yes" },
new SelectListItem { Value = "2",Text = "No" }
};
cancelled = data.ToList();
return cancelled;
}
Controller:
if(cancelled == 2)
{
cancelled = null;
}
But I got the same results. When I selected No in the filter and went to the second page, Yes was in the dropdown instead of No.
I debugged and found that the value of the parameter cancelled of the method in the controller is null when I went to the second page.
How to keep the selected value from the dropdown when the page is changed?
Your code is generating <option> elements with values of "1" and "NULL". The text "NULL" is not the same as null value (which is recognized by an empty string - i.e. it has no value). If the value of property cancelled is null then the first option will be selected because there is no option element with an empty value (and because something has to be selected)
In order for it to be selected, your element needs to be <option value="">No</option> which you can generate using either
public IEnumerable<SelectListItem> cancelledForDp()
{
return new List<SelectListItem>()
{
new SelectListItem { Value = "1",Text = "Yes" },
new SelectListItem { Value = "",Text = "No" }
};
}
or
public IEnumerable<SelectListItem> cancelledForDp()
{
return new List<SelectListItem>()
{
new SelectListItem { Value = "1", Text = "Yes" },
};
}
and in the view use
#Html.DropDownList("cancelled", (IEnumerable<SelectListItem>)ViewBag.cancelledDp, "No", new { id = "chosenCancelled" })
where the 3rd parameter creates the labelOption with a null value.
As a side note, if your field can only store 2 values, then you should be using as database BIT field so that the property is
public bool IsCancelled { get; set; }
not int? cancelled (or is it string cancelled?)
and simply use
#Html.CheckBoxFor(m => m.IsCancelled)
in the view. I also recommend you always use the strongly typed ***For() methods.

Choosing selected item for dropdown list in action

I have a page which allows users to change their privacy settings for:
Their posted recipes
Their profile
Their posted lists
I am trying to form my code so that when the users load this page, the dropdown lists which they use to select their privacy settings display their current setting, so if they had their recipe privacy set to "Registered users", whenever they load the privacy settings page I want it to start off with "Registered users" selected.
Initially I create a list of SelectListItem instances called PrivacySettings
List<SelectListItem> PrivacySettings = new List<SelectListItem>();
PrivacySettings.Add(
new SelectListItem
{
Text="Anybody",
Value = "0"
});
PrivacySettings.Add(
new SelectListItem
{
Text = "Registered users",
Value = "1"
});
PrivacySettings.Add(
new SelectListItem
{
Text = "Only me",
Value = "2"
});
Then I create three separate SelectList instances. Here is the part where I am assigning the selected value for each of the lists to the first value which matches the user's saved setting.
SelectList RecipePrivacyList = new SelectList(
PrivacySettings,
"Value",
"Text",
PrivacySettings.First(x => x.Value == LoggedInUser.RecipePrivacy.ToString()));
SelectList ProfilePrivacyList = new SelectList(
PrivacySettings,
"Value",
"Text",
PrivacySettings.First(x => x.Value == LoggedInUserProfile.Privacy.ToString()));
SelectList ListPrivacyList = new SelectList(
PrivacySettings,
"Value",
"Text",
PrivacySettings.First(x => x.Value == LoggedInUser.ListPrivacy.ToString()));
Then I assign each of these to separate ViewData keys
ViewData["RecipePrivacy"] = RecipePrivacyList;
ViewData["ProfilePrivacy"] = ProfilePrivacyList;
ViewData["ListPrivacy"] = ListPrivacyList;
In my view I retrieve these and store them into variables
var ProfilePrivacy = (SelectList)ViewBag.ProfilePrivacy;
var RecipePrivacy = (SelectList)ViewBag.RecipePrivacy;
var ListPrivacy = (SelectList)ViewBag.ListPrivacy;
And finally I use the Html.DropDownList() helper method to create the lists using the aforementioned variables
#Html.DropDownList("profile-privacy", ProfilePrivacy, new { #class = "profile-privacy" })
When the view is loaded, the first value ("Anyone" or value 0) is selected regardless of the user's actual setting.
you have to set the selected item of the SelectList like that:
SelectList ListPrivacyList = new SelectList(
PrivacySettings,
"Value",
"Text",
PrivacySettings.First(x => x.Value == LoggedInUser.ListPrivacy.ToString()).Value);

DropDownListFor() not setting to the model value

I'm looping over my model but the value that is coming from the model isn't what's showing in the drop down list as the selected item. Instead the list is always just showing the first entry.
#Html.DropDownListFor(modelItem => item.RecordType, Model.RecordTypes, new { id="recordType_" + item.TransactionID })
item.RecordType has a value of 5 from the model (I print it out so I know it's that value). However the drop down shows "Initial" (which is a value of 4) instead of "Firm" (which is the valu eof 5 which is what our model item value is). The list in the source is defined as:
<select data-val="true" data-val-number="The field RecordType must be a number." id="recordType_63" name="item.RecordType">
<option value="4">Initial</option>
<option value="5">Firm</option>
<option value="6">Announced</option>
<option value="7">N/A</option>
</select>
How do I set the drop down to be what the model value is?
public IEnumerable<SelectListItem> RecordTypes
{
//get { return new SelectListItem(recordTypes, "RECORD_TYPE_ID", "RECORD_TYPE"); }
get
{
return (from r in recordTypes
select new SelectListItem { Text = r.RECORD_TYPE, Value = r.RECORD_TYPE_ID.ToString() });
}
}
You can do that by creating a SelectList in your Html.DropDownListFor like:
#Html.DropDownListFor(modelItem => item.RecordType, new SelectList(Model.RecordTypes, item.RecordType), new { id="recordType_" + item.TransactionID });
This passes your IEnumerable<SelectListItem> into the constructor along with a parameter, in this case item.RecordType, letting it know which item to select.
EDIT: In response to comment
You could use the overload of SelectList which allows you to specify the DataTextField and DataValueField in your case these would be Text and Value respectively.
or
Re-work your Model.RecordTypes to return a SelectList and do the necessary work in there, you could use a method and pass in the value to select. Something like:
public SelectList RecordTypes(object selectedValue)
{
return new SelectList(recordTypes, "RECORD_TYPE", "RECORD_TYPE_ID", selectedValue);
}
Hope that helps.
When you are assembling your RecordTypes SelectListItem collection, make sure to set Selected = true for the currently selected item-- it will not set it for you.
Assuming the RecordType variable on your view model mates up against the RECORD_TYPE_ID variable of your data set, you can update creation of variable to:
from r in recordTypes
select new SelectListItem { Text = r.RECORD_TYPE, Value = r.RECORD_TYPE_ID.ToString(), Selected = r.RECORD_TYPE_ID == this.RecordType }
If you are re-using the RecordTypes variable across multiple dropdowns on the view, you're going to have to change your approach and create the IEnumerable<SelectListItem> for each dropdown. Suchas:
#Html.DropDownListFor(modelItem => item.RecordType, RecordTypes.Select(rt => new SelectListItem { Text = rt.Text, Value = rt.Value, Selected = rt.Value == item.RecordType}))

How to set the dropdown display default to "Medium" and not to be "High"?

Code:
public enum PriorityEnum
{
High,
Medium,
Low
}
IQueryable<PriorityValues> priorityValues = _enumReadService.GetRecords<PriorityValues>();
var creationOptions = new CreationOptions
{
PriorityValues = priorityValues.ToList()
};
I am getting the dropdown displaying default to "High". But it needs to be "Medium". How to set the dropdown display default to "Medium" and not to be "High"?
Update: Adding the rendering dropdown code
<b>#Html.Label("Priority:")</b>
#Html.DropDownListFor(x => x.PriorityValueId, Enum.GetValues(typeof (PriorityValueEnum)).OfType<PriorityValueEnum>().ToList().Select(x => new SelectListItem {Text = x.ToString(), Value = ((int) x).ToString(CultureInfo.InvariantCulture)}))
You haven't shown how you rendered the DropDown, but if you used the following:
#Html.DropDownListFor(x => x.Priority, Model.PriorityValues)
all you need to do is set the value of the Priority property in the controller action to the desired result:
IEnumerable<SelectListItem> priorityValues = ...
model.PriorityValues = priorityValues;
model.Priority = (int)PriorityEnum.Medium;
return View(model);

trying to set a dropdown in MVC

I almost have this solved but need a little push.
Here's what I have:
In the database I have a field called active that is a bit field (True/False)
I have placed a dropdownlist on the View form like this:
<%= Html.DropDownList("lstActive", new SelectList((IEnumerable)ViewData["ActiveList"])) %>
In my controller, I simply have this code to generate the True/False in the dropdown:
List<string> activeList = new List<string>();
activeList.Add("True");
activeList.Add("False");
ViewData["ActiveList"] = new SelectList(activeList);
I want to bind to the field in the database called active and select it in the dropdown. When I view it like this I get this:
alt text http://rjmueller.net/sitesimages/temp/dropdown.gif
So the questions are these:
Obviously I am not pointing to the Value and Text property but what is that in this case?
And how do I select the value that is in the database?
Any help would be appreciated.
First, this is probably better suited to radio buttons, not a select. Second, you really ought to have a view model with a property that is an IEnumerable<SelectListItem> that supplies the values for the select. You can construct that directly in the model.
var model = new ViewModel();
model.ActiveList = new List<SelectListItem>
{
new SelectListItem { Text = "Yes", Value = "true" },
new SelectListITem { Text = "No", Value = "false" }
};
model.Active = false; // this will be the default
return View( model );
Then in your view (strongly-typed to your view model type):
<%= Html.DropDownListFor( m => m.Active, Model.ActiveList ) %>
Using radio buttons, you can omit the list (since there are only the two choices).
<%= Html.RadioButtonFor( m => m.Active, true ) %> Yes
<%= Html.RadioButtonFor( m => m.Active, false ) %> No
Here's a couple of suggestions for you.
First, your DropdownList's name is "lstActive", so if you create a List<SelectListItem> called "lstActive" and pass that back in ViewData, you don't have to do anything fancy with boxing. Then your declaration looks like:
<%= Html.DropDownList("lstActive") %>
easy, huh?
In your controller, you create your List. Here's a method I've used:
private List<SelectListItem> GetAccounts(User user)
{
var items = new List<SelectListItem>();
foreach (Account account in user.Accounts)
{
var item = new SelectListItem();
item.Text = account.Name;
item.Value = account.AccountId.ToString();
if (ActiveAccount == account.AccountId)
item.Selected = true;
items.Add(item);
}
return items;
}
Basically, what I'm trying to point out is that you can set a property on your SelectListItem that you wish to be displayed as selected. Here, I'm using my own code for Users and Accounts, but you'd substitute your own data based on your db query.
First thing, you're recreating a SelectList the ViewData data, you should declare the DropBox as follows:
<%= Html.DropDownList("lstActive", ViewData["ActiveList"]) %>
Second, instead of creating a generic list on the controller, create a SelectList and add SelectListItems to it:
var activeList = new SelectList
{
new SelectListItem { Text = "True", Value = true },
new SelectListItem { Text = "False", Value = false }
};
ViewData["ActiveList"] = activeList;
This should clarify:
Drop-down Lists and ASP.NET MVC
For each select list element you need to set the Text and Value properties...
One solution could be as follows:
Model:
public class NameValue
{
public string Name { get; set; }
public string Value { get; set; }
}
Controller:
string currentActiveValue = myDB.active.ToString();
List<NameValue> yesNoList = new List<NameValue>
{
new NameValue { Name = "Yes", Value = "True" },
new NameValue { Name = "No", Value = "False" }
};
SelectList myActiveList = new SelectList(yesNoList, "Name", "Value", currentActiveValue);
ViewData["ActiveList"] = myActiveList;
View:
div>Is Active: <%= Html.DropDownList("ActiveList") %></div>

Categories

Resources