DropDownList does not get selected using with HtmlHelper.DropDownListFor - asp.net-mvc-2

I render a dropdown list to allow the user to select the enum value using this solution http://blogs.msdn.com/b/ukadc/archive/2010/06/22/asp-net-mvc-creating-a-dropdownlist-helper-for-enums.aspx.
this is the helper
public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
IEnumerable<TEnum> values = Enum.GetValues(typeof(TEnum)).Cast<TEnum>();
IEnumerable<SelectListItem> items =
values.Select(value => new SelectListItem
{
Text = CultureLocalizationHelper.GetString(value.ToString(), typeof(SiteResources.Core.Views.CulturalConfiguration.Index)),
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
});
return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
}
This approach works very well with any enum but not with this
public enum Color
{
Orange = 1,
Green = 2,
Blue = 3,
Primary = 4
}
I have a very weird problem, the helper does not work with this enum.
I debug the SelectListItems and there's one that is selected but DropDownListFor does not render any of the elements with selected="selected"
Any idea?
Thanks for your time!

specify a new SelectList(values, selectedValue) instead of specifying the SelectListItems directly to set the selected value
<%: Html.DropDownListFor(model=> model.Type, new SelectList(Enum.GetValues(typeof(UserType)), (Model??new User()).Type)) %>

One way is to overload an Enum ToString() and/or create your own Attribute as described in http://lostinloc.com/2008/05/06/c-overloading-an-enums-tostring/.

Related

ZK: loading value/text into selectbox

I have a selectbox and want to load the value and text into the template, similar to an HTML dropdown box. I am using ZK framework with Java on the back end.
<selectbox id="buListbox" model="${$composer.buModel}" >
<template name="model">
<label value="${each}" />
</template>
</selectbox>
When using ZK, you don't need the value to identify the selected object like in HTML.
When using the MVC pattern, binding a model via model attribute, the selected item is also stored in that model and can be retrieved in java via model.getSelection().
Furthermore, a model is not restricted to lists of String, but it can hold any object type you want. In the template section, you can display any property of that object. Then the properties' toString() method is used to get the value which is displayed. This also applies to ${each} itself.
Example:
Assuming your model is a ListModelList of type ValueType:
public class ValueType {
private String value;
private String text;
public ValueType(String value, String text) {
this.value=value;
this.text=text;
}
public String getText() {
return this.text;
}
public String getValue() {
return this.value;
}
}
private ListModelList<ValueType> typesModel;
public ListModelList<ValueType> getTypesModel() {
return typesModel;
}
You than can use the selectbox's model/template to display it's text property:
<selectbox id="typesSelectbox" model="${$composer.typesModel}">
<template name="model">
${each.text}
</template>
</selectbox>
In java, you then get the selected item via typeModel.getSelection() .
Here you can find a working ZKFiddle example.

Formatting dates in an MVC Dropdown

I have a dropdown list on my page as so: -
#Html.DropDownList("dd_dates", new SelectList(#Model.seasonDates), "Please Select")
where seasonDates is an IList of dates. The problem is that when the dates are displayed in the dropdown they also have the time on them as well. How do I format the display date so that the time is not included.
Maybe a better way to do this would be to define a property in your model that returns IEnumerable<SelectListItem> (in your model class):
public DateTime SelectedDate {get;set;}
public IEnumerable<SelectListItem> SeasonDates
{
get
{
foreach (var item in seasonDates)
yield return new SelectListItem()
{
Text = item.ToShortDateString(), // or apply your own formatting!
Value = item
};
}
}
Then use this in the view:
#Html.DropDownListFor(m => m.SelectedDate, #Model.SeasonDates, "Please Select")
Apologies if there are errors, I dont have VS open to verify the sytanx.

how to convert Enum to IEnumerable<SelectListItem>

UPDATE 1
I want to populate a listboxfor mvc helper to render list items in View. I don't know how to pass the second parameter to the helper, which accepts IENumerableSelectListItem SelectionList.
Html.ListBoxFor(model => model.SelectedDate, Model.DateList, new { })
I am having a property in my model class,
public IEnumerableSelectListItem DateList { get; set; }
and somehow i need to populate DateList from my controller action method, which fills up all the other model properties and passes it to a partial view where i have the helper. DateList should be getting the values from an Enum DateListEnum
Any ideas on how to go about doing this. Also let me know how do i ensure that a single list item is selected at a time...i am really new to all these..and its been quite some time i am working on this...but nothing came up so far....
I am having below code in my controller action method,
model.DateList = getDateList();
which calls this method,
public IEnumerableSelectListItem getDateList()
{
IEnumerableSelectListItem values = Enum.GetValues(typeof(DateListEnum));
//this one doesn't work because of casting issues and this is where i want to convert Enum Values to IEnumerableSelectListItem
return values;
}
UPDATE 2
i have the listbox working and its displaying in the UI based upon below code
` IEnumerable<SelectListItem> values = Enum.GetNames(typeof(ColumnFormattingDateFormats)).Cast<ColumnFormattingDateFormats>().Select(p => new SelectListItem()
{
Text = p.ToString(),
Value = ((int)p).ToString()
}).ToList();`
But now i am having few other problems,
the enum that i am using is
`public enum ColumnFormattingDateFormats : int
{
[StringValue("Wednesday, March 14, 2001")]
FULLDATE = 0,
[StringValue("3/14")]
MMDDWSLASH = 1,
[StringValue("3/14/01")]
MMDDYYWSLASH = 2,
[StringValue("03/14/01")]
MMDDYYWMMZEROPREFIXWSLASH = 3
}`
and my helper looks like this,
Html.ListBoxFor(model => model.SelectedDate, Model.DateList, new { })
1> How do i pass the selected item to the listboxfor helper?
is there a way to pass the selected item to the helper through the property
[DataMember]
public ColumnFormattingDateFormats SelectedDate{ get; set; }
in my model class? to begin with i am passing
this.SelectedDate= ColumnFormattingDateFormats.FULLDATE;
to the default constructor in my model class...but for some reason the first parameter model => model.SelectedDatehas some problem with that..throws null exception...
2> how do i ensure [StringValue] from Enum gets displayed in UI listbox element and not the Enum Text for ex. FULLDATE should not be getting displayed, instead "Wednesday, March 14, 2001" should be?
3> How do i ensure that a single item is selected without using livequery?
My brains are all fried up now....any directions anyone?????
how about:
Enum.GetValues(typeof(MyEnum))
.Cast<MyEnum>()
.Select(p => new SelectListItem()
{
Text = p.ToString(),
Value = ((int) p).ToString()
})
.ToList();

How do I get EF to persist empty strings as NULL?

In my domain, there's no important distinction between NULL and an empty string. How do I get EF to ignore the difference between the two and always persist an empty string as NULL?
Empty string is not default value for string property so it means your code is setting empty strings somewhere. In such case it is your responsibility to handle it.
If you are using code first with POCOs you can use custom setter:
private string _myProperty;
public string MyProperty
{
get { return _myProperty; }
set
{
if (value == String.Empty)
{
_myProperty = null;
}
else
{
_myProperty = value;
}
}
}
Here is a function I placed in my DbContext subclass that replaces empty or whitespace strings with null.
I still didn't optimize it so any performance hints will be very appreciated.
private const string StringType = "String";
private const EntityState SavingState = EntityState.Added | EntityState.Modified;
public override int SaveChanges()
{
var objectContext = ((IObjectContextAdapter)this).ObjectContext;
var savingEntries =
objectContext.ObjectStateManager.GetObjectStateEntries(SavingState);
foreach (var entry in savingEntries)
{
var curValues = entry.CurrentValues;
var fieldMetadata = curValues.DataRecordInfo.FieldMetadata;
var stringFields = fieldMetadata.Where(f =>
f.FieldType.TypeUsage.EdmType.Name == StringType);
foreach (var stringField in stringFields)
{
var ordinal = stringField.Ordinal;
var curValue = curValues[ordinal] as string;
if (curValue != null && curValue.All(char.IsWhiteSpace))
curValues.SetValue(ordinal, null);
}
}
return base.SaveChanges();
}
Optimization considerations:
Identify a string type property by different way other than string comparison I tried to look-up some enumeration of the built-in types but didn't find
Cache string fields for types (maybe is unnecessary, will have to decompile and see what the original impl does
Order result by entity type, backup iterated entity type, if next iterated entity is same type, use previous metadata, again, if the metadata is anyway there, performance is cheaper the way it is
Limit string length for whitespace check - i.e. if a string length > x, skip checking whether its a whitespace string or not
I'm using Silverlight and the TextBoxes in the UI set all the string properties to empty strings.
I tried setting:
<TextBox
Text="{Binding MyStringProperty,
Mode=TwoWay,
ValidatesOnDataErrors=True,
TargetNullValue=''}"/>
But it didn't help much.
That's not Entity Framework's job.
You should do it in your repository, or in the database with triggers.
Or do it at the start (e.g when the data comes in, UI, external source, etc)

ASP.NET GetFullHtmlFieldId not returning valid id

In MVC2 template, I normally use this.ViewData.TemplateInfo.GetFullHtmlFieldId(fieldName)
to generate the id field of an html element. This has worked in most of the cases.
However this method does not actually return valid id field, it merely prefix fieldName with ViewData.TemplateInfo.HtmlFieldPrefix, this is causing problems for me when rendering collections which has [] in the HtmlFieldPrefix.
I have been manually converting those characters to _ where I find the need, but this seems to be not elegant (repeated code), has anyone found a good way to generate id field properly?
Can you be more specific about the kind of problems do you have?
For example, there is an elegant approach to editing variable length list with validation support provided. While it doesn't use templates still remains DRY with partial views.
While the ids are inconsistent - the names are OK and only problem I encountered is that using jquery.infieldlabel it appeared that label's for attribute (generated by GetFullHtmlFieldId inside LabelFor helper) didn't match id of the appropriate TextBoxFor input. So I created LabelForCollectionItem helper method that just uses the same method for id generation as the TextBox - TagBuilder.GenerateId(fullName)
Maybe the code doesn't correspond to your need but hope it will help somebody since I found your question among the first searching for solution to my problem.
public static class LabelExtensions
{
/// <summary>
/// Generates Label with "for" attribute corresponding to the id rendered by input (e.g. TextBoxFor),
/// for the case when input is a collection item (full name contains []).
/// GetFullHtmlFieldId works incorrect inside Html.BeginCollectionItem due to brackets presense.
/// This method copies TextBox's id generation.
/// </summary>
public static MvcHtmlString LabelForCollectionItem<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression,
string labelText = null, object htmlAttributes = null) where TModel : class
{
var tag = new TagBuilder("label");
tag.MergeAttributes(new RouteValueDictionary(htmlAttributes)); // to convert an object into an IDictionary
// set inner text
string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
string innerText = labelText ?? GetDefaultLabelText(html, expression, htmlFieldName);
if (string.IsNullOrEmpty(innerText))
{
return MvcHtmlString.Empty;
}
tag.SetInnerText(innerText);
// set for attribute
string forId = GenerateTextBoxId(tag, html, htmlFieldName);
tag.Attributes.Add("for", forId);
return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
}
/// <summary>
/// Extracted from System.Web.Mvc.Html.InputExtensions
/// </summary>
private static string GenerateTextBoxId<TModel>(TagBuilder tagBuilder, HtmlHelper<TModel> html, string htmlFieldName)
{
string fullName = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName);
tagBuilder.GenerateId(fullName);
string forId = tagBuilder.Attributes["id"];
tagBuilder.Attributes.Remove("id");
return forId;
}
/// <summary>
/// Extracted from System.Web.Mvc.Html.LabelExtensions
/// </summary>
private static string GetDefaultLabelText<TModel, TValue>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, string htmlFieldName)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
return labelText;
}
}