独自の種類のパラメーターを使用して MultiSelectList を構築するための MVC ヘルパーを構築しようとしています。少し前に作成した SelectFor ヘルパーに基づいています。SelectFor は次のようになります。
public delegate object Property<T>(T property);
public delegate object Property<T, K>(T property, K propertyKey);
public static HtmlString SelectFor<TModel, TProperty, TListItem>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> forExpression,
IEnumerable<TListItem> enumeratedItems,
Property<TListItem> idExpression,
Property<TListItem> displayExpression,
Property<TListItem> titleExpression,
object htmlAttributes,
bool blankFirstLine) where TModel : class
{
//initialize values
var metaData = ModelMetadata.FromLambdaExpression(forExpression, htmlHelper.ViewData);
var propertyName = metaData.PropertyName;
var propertyValue = htmlHelper.ViewData.Eval(propertyName).ToStringOrEmpty();
var enumeratedType = typeof(TListItem);
//build the select tag
var returnText = string.Format("<select id=\"{0}\" name=\"{0}\"", HttpUtility.HtmlEncode(propertyName));
if (htmlAttributes != null)
{
foreach (var kvp in htmlAttributes.GetType().GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(htmlAttributes, null)))
{
returnText += string.Format(" {0}=\"{1}\"", HttpUtility.HtmlEncode(kvp.Key),
HttpUtility.HtmlEncode(kvp.Value.ToStringOrEmpty()));
}
}
returnText += ">\n";
if (blankFirstLine)
{
returnText += "<option value=\"\"></option>";
}
//build the options tags
foreach (TListItem listItem in enumeratedItems)
{
var idValue = idExpression(listItem).ToStringOrEmpty();
var displayValue = displayExpression(listItem).ToStringOrEmpty();
var titleValue = titleExpression(listItem).ToStringOrEmpty();
returnText += string.Format("<option value=\"{0}\" title=\"{1}\"",
HttpUtility.HtmlEncode(idValue), HttpUtility.HtmlEncode(titleValue));
if (idValue == propertyValue)
{
returnText += " selected=\"selected\"";
}
returnText += string.Format(">{0}</option>\n", displayValue);
}
//close the select tag
returnText += "</select>";
return new HtmlString(returnText);
}
MultiSelectFor はわずかに異なるだけで、重要な違いが 1 つあります。は のプロパティ タイプのforExpression
ジェネリックになります。このコレクションは、リスト項目を「事前選択」するために使用され、フォーム上で選択された項目の戻り値になります。私はこれでさらに進んだ(と思う)が、まだかなり迷っている.IEnumerable
idExpression
public static HtmlString MultiSelectListFor<TModel, TProperty, TProperty, TPropertyKey>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, IEnumerable<TPropertyKey>>> forExpression,
IEnumerable<TProperty> enumeratedItems,
Property<TProperty, TPropertyKey> idExpression,
Property<TProperty> displayExpression,
Property<TProperty> titleExpression,
object htmlAttributes) where TModel : class
{
//initialize values
var metaData = ModelMetadata.FromLambdaExpression(forExpression, htmlHelper.ViewData);
var propertyName = metaData.PropertyName;
var propertyValue = htmlHelper.ViewData.Eval(propertyName).ToStringOrEmpty();
var enumeratedType = typeof(TProperty);
//build the select tag
var returnText = string.Format("<select multiple=\"multiple\" id=\"{0}\" name=\"{0}\"", HttpUtility.HtmlEncode(propertyName));
if (htmlAttributes != null)
{
foreach (var kvp in htmlAttributes.GetType().GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(htmlAttributes, null)))
{
returnText += string.Format(" {0}=\"{1}\"", HttpUtility.HtmlEncode(kvp.Key),
HttpUtility.HtmlEncode(kvp.Value.ToStringOrEmpty()));
}
}
returnText += ">\n";
//build the options tags
foreach (TProperty listItem in enumeratedItems)
{
//this part here needs to change:
var idValue = ???.ToStringOrEmpty();
var displayValue = displayExpression(listItem).ToStringOrEmpty();
var titleValue = titleExpression(listItem).ToStringOrEmpty();
returnText += string.Format("<option value=\"{0}\" title=\"{1}\"",
HttpUtility.HtmlEncode(idValue), HttpUtility.HtmlEncode(titleValue));
if (propertyValue.Contains(idValue))
{
returnText += " selected=\"selected\"";
}
returnText += string.Format(">{0}</option>\n", displayValue);
}
//close the select tag
returnText += "</select>";
return new HtmlString(returnText);
}
助けていただければ幸いです。
更新 答えてくれてありがとう!ジェネリックは時々私を混乱させます。完全なソリューションは次のとおりです。
public delegate object Property<T>(T property);
public static HtmlString MultiSelectListFor<TModel, TKey, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, IEnumerable<TKey>>> forExpression,
IEnumerable<TProperty> enumeratedItems,
Func<TProperty, TKey> idExpression,
Property<TProperty> displayExpression,
Property<TProperty> titleExpression,
object htmlAttributes) where TModel : class
{
//initialize values
var metaData = ModelMetadata.FromLambdaExpression(forExpression, htmlHelper.ViewData);
var propertyName = metaData.PropertyName;
var propertyValue = htmlHelper.ViewData.Eval(propertyName).ToStringOrEmpty();
var enumeratedType = typeof(TProperty);
//build the select tag
var returnText = string.Format("<select multiple=\"multiple\" id=\"{0}\" name=\"{0}\"", HttpUtility.HtmlEncode(propertyName));
if (htmlAttributes != null)
{
foreach (var kvp in htmlAttributes.GetType().GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(htmlAttributes, null)))
{
returnText += string.Format(" {0}=\"{1}\"", HttpUtility.HtmlEncode(kvp.Key),
HttpUtility.HtmlEncode(kvp.Value.ToStringOrEmpty()));
}
}
returnText += ">\n";
//build the options tags
foreach (TProperty listItem in enumeratedItems)
{
var idValue = idExpression(listItem).ToStringOrEmpty();
var displayValue = displayExpression(listItem).ToStringOrEmpty();
var titleValue = titleExpression(listItem).ToStringOrEmpty();
returnText += string.Format("<option value=\"{0}\" title=\"{1}\"",
HttpUtility.HtmlEncode(idValue), HttpUtility.HtmlEncode(titleValue));
if (propertyValue.Contains(idValue))
{
returnText += " selected=\"selected\"";
}
returnText += string.Format(">{0}</option>\n", displayValue);
}
//close the select tag
returnText += "</select>";
return new HtmlString(returnText);
}
public static HtmlString MultiSelectListFor<TModel, TKey, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, IEnumerable<TKey>>> forExpression,
IEnumerable<TProperty> enumeratedItems,
Func<TProperty, TKey> idExpression,
Property<TProperty> displayExpression,
Property<TProperty> titleExpression) where TModel : class
{
return htmlHelper.MultiSelectListFor(forExpression, enumeratedItems, idExpression, displayExpression, titleExpression, null);
}
助けてくれてありがとう!