迷失在仿制药和反思酱中
本文关键字:迷失 | 更新日期: 2023-09-27 18:28:29
我正在尝试构建一个MVC助手,用于使用我自己的参数构建MultiSelectList。我把它建立在一个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只是略有不同,有一个显著性差异:forExpression
将是idExpression
属性类型的通用IEnumerable
。此集合将用于"预选"列表项目,并将作为表单上所选项目的返回值。我(我认为)在这方面做得更远,但仍然很失落。
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);
}
感谢您的帮助。
更新谢谢你的回答!Generics有时会让我感到困惑。完整的解决方案如下:
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);
}
再次感谢您的帮助!
听起来你在要求
Expression<Func<TModel, IEnumerable<TListItem>>
您需要制作一个单独的泛型参数,并将其用于ID属性和for表达式:
public static HtmlString MultiSelectListFor<TModel, TKey, TListItem>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, IEnumerable<TKey>>> forExpression,
IEnumerable<TListItem> enumeratedItems,
Func<TListItem, TKey> idExpression,