Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何获得';IEnumerable中的模型元数据是什么?_C#_Asp.net Mvc_Asp.net Mvc 4 - Fatal编程技术网

C# 如何获得';IEnumerable中的模型元数据是什么?

C# 如何获得';IEnumerable中的模型元数据是什么?,c#,asp.net-mvc,asp.net-mvc-4,C#,Asp.net Mvc,Asp.net Mvc 4,我在MVC中有GridView,它的构造方式如下: @模型IEnumerable @(Html.GridFor() .WithName("PageOverviewGrid") .WithColumns(model => { model.Bind(x => x.Name); model.Bind(x => x.DateCreated); model.Bind(x => x.Dat

我在MVC中有GridView,它的构造方式如下:

@模型IEnumerable

@(Html.GridFor()
      .WithName("PageOverviewGrid")
      .WithColumns(model =>
      {
          model.Bind(x => x.Name);
          model.Bind(x => x.DateCreated);
          model.Bind(x => x.DateUpdated);
      })
)
您在上面看到的是,我正在为我的模型构建一个网格,它是一个IEnumerable,我将3列绑定到它

我的HtmlHelper的代码如下:

/// <summary>
///     Provides a way to extend the <see cref="HtmlHelper" />.
/// </summary>
public static class HtmlHelperExtensions
{
    #region Grid

    /// <summary>
    ///     Constructs a grid for a given model by using a fluent API.
    /// </summary>
    /// <typeparam name="TModel">The type of the model that is bound to the grid.</typeparam>
    /// <param name="htmlHelper">The <see cref="HtmlHelper" /> which is used to create the grid.</param>
    /// <returns>An <see cref="IGridBuilder{TModel}" /> that is used to construct the grid.</returns>
    public static IGridBuilder<TModel> GridFor<TModel>(this HtmlHelper<IEnumerable<TModel>> htmlHelper)
    {
        return new GridBuilder<TModel>(htmlHelper);
    }

    #endregion
}
/// <summary>
///     When implemented on a class, this class acts as an <see cref="IHtmlString" /> that can construct a grid by using a
///     fluent API.
/// </summary>
/// <typeparam name="TModel">The type of the model that is bound to the grid.</typeparam>
public interface IGridBuilder<TModel> : IHtmlString
{
    #region Properties

    /// <summary>
    ///     Gets the name of the <see cref="IGridBuilder{TModel}" />.
    ///     The outer div of the grid will have an id that matches this name.
    /// </summary>
    string Name { get; }

    /// <summary>
    ///     The <see cref="HtmlHelper" /> that is used to build the grid.
    /// </summary>
    HtmlHelper HtmlHelper { get; }

    #endregion

    #region Methods

    /// <summary>
    ///     Sets the name of the <see cref="IGridBuilder{TModel}" />.
    /// </summary>
    /// <param name="name">The name that the <see cref="IGridBuilder{TModel}" /> should have.</param>
    /// <returns>An <see cref="IGridBuilder{TModel}" /> that is used to construct the grid.</returns>
    IGridBuilder<TModel> WithName(string name);

    /// <summary>
    ///     Set the columns of the model that should be bound to grid.
    /// </summary>
    /// <param name="bindAllColumns">The action that will bind all the columns.</param>
    /// <returns>An <see cref="IGridBuilder{TModel}" /> that is used to construct the grid.</returns>
    IGridBuilder<TModel> WithColumns(Action<IGridBuilder<TModel>> bindAllColumns);

    /// <summary>
    ///     Binds an column to the grid.
    /// </summary>
    /// <typeparam name="TItem">The type of the column on which to bind the items.</typeparam>
    /// <param name="propertySelector">The functional that will bind the control to the grid.</param>
    void Bind<TItem>(Expression<Func<TModel, TItem>> propertySelector);

    #endregion
}
//
///提供了一种扩展的方法。
/// 
公共静态类HtmlHelperExtensions
{
#区域网格
/// 
///使用fluent API为给定模型构造网格。
/// 
///绑定到栅格的模型的类型。
///用于创建网格的。
///用于构造网格的。
公共静态IGridBuilder GridFor(此HtmlHelper HtmlHelper)
{
返回新的GridBuilder(htmlHelper);
}
#端区
}
我将在此方法中返回一个接口,以允许通过fluent API进行构造。 该接口的代码如下所示:

/// <summary>
///     Provides a way to extend the <see cref="HtmlHelper" />.
/// </summary>
public static class HtmlHelperExtensions
{
    #region Grid

    /// <summary>
    ///     Constructs a grid for a given model by using a fluent API.
    /// </summary>
    /// <typeparam name="TModel">The type of the model that is bound to the grid.</typeparam>
    /// <param name="htmlHelper">The <see cref="HtmlHelper" /> which is used to create the grid.</param>
    /// <returns>An <see cref="IGridBuilder{TModel}" /> that is used to construct the grid.</returns>
    public static IGridBuilder<TModel> GridFor<TModel>(this HtmlHelper<IEnumerable<TModel>> htmlHelper)
    {
        return new GridBuilder<TModel>(htmlHelper);
    }

    #endregion
}
/// <summary>
///     When implemented on a class, this class acts as an <see cref="IHtmlString" /> that can construct a grid by using a
///     fluent API.
/// </summary>
/// <typeparam name="TModel">The type of the model that is bound to the grid.</typeparam>
public interface IGridBuilder<TModel> : IHtmlString
{
    #region Properties

    /// <summary>
    ///     Gets the name of the <see cref="IGridBuilder{TModel}" />.
    ///     The outer div of the grid will have an id that matches this name.
    /// </summary>
    string Name { get; }

    /// <summary>
    ///     The <see cref="HtmlHelper" /> that is used to build the grid.
    /// </summary>
    HtmlHelper HtmlHelper { get; }

    #endregion

    #region Methods

    /// <summary>
    ///     Sets the name of the <see cref="IGridBuilder{TModel}" />.
    /// </summary>
    /// <param name="name">The name that the <see cref="IGridBuilder{TModel}" /> should have.</param>
    /// <returns>An <see cref="IGridBuilder{TModel}" /> that is used to construct the grid.</returns>
    IGridBuilder<TModel> WithName(string name);

    /// <summary>
    ///     Set the columns of the model that should be bound to grid.
    /// </summary>
    /// <param name="bindAllColumns">The action that will bind all the columns.</param>
    /// <returns>An <see cref="IGridBuilder{TModel}" /> that is used to construct the grid.</returns>
    IGridBuilder<TModel> WithColumns(Action<IGridBuilder<TModel>> bindAllColumns);

    /// <summary>
    ///     Binds an column to the grid.
    /// </summary>
    /// <typeparam name="TItem">The type of the column on which to bind the items.</typeparam>
    /// <param name="propertySelector">The functional that will bind the control to the grid.</param>
    void Bind<TItem>(Expression<Func<TModel, TItem>> propertySelector);

    #endregion
}
//
///在类上实现时,该类充当可以使用
///流畅的API。
/// 
///绑定到栅格的模型的类型。
公共接口IGridBuilder:IHtmlString
{
#区域属性
/// 
///获取文件的名称。
///网格的外部div将具有与此名称匹配的id。
/// 
字符串名称{get;}
/// 
///用于构建网格的。
/// 
HtmlHelper HtmlHelper{get;}
#端区
#区域方法
/// 
///设置文件的名称。
/// 
///应具有的名称。
///用于构造网格的。
IGridBuilder WithName(字符串名称);
/// 
///设置应绑定到轴网的模型列。
/// 
///将绑定所有列的操作。
///用于构造网格的。
IGridBuilder with columns(Action bindAllColumns);
/// 
///将列绑定到网格。
/// 
///要在其上绑定项的列的类型。
///将控件绑定到网格的函数。
void Bind(表达式属性选择器);
#端区
}
当然,我还有它的实施:

/// <summary>
///     An implementation of the <see cref="IGridBuilder{TModel}" /> that is used to build a grid.
/// </summary>
/// <typeparam name="TModel">The type of the model that is bound to the grid.</typeparam>
public class GridBuilder<TModel> : IGridBuilder<TModel> 
{
    #region Constructors

    /// <summary>
    ///     Creates a new instance of the <see cref="GridBuilder{TModel}" />.
    /// </summary>
    /// <param name="htmlHelper">The <see cref="HtmlHelper{TModel}" /> that is used to render this one.</param>
    public GridBuilder(HtmlHelper<IEnumerable<TModel>> htmlHelper)
    {
        HtmlHelper = htmlHelper;
        properties = new Dictionary<string, List<string>>();
    }

    #endregion

    #region Properties

    /// <summary>
    ///     A <see cref="List{TKey}" /> that conains the names of the property and the display name that belongs
    ///     to the property.
    /// </summary>

    public readonly Dictionary<string, List<string>> properties;

    #endregion

    #region IGridBuilder Members

    /// <summary>
    ///     Gets the name of the <see cref="IGridBuilder{TModel}" />.
    ///     The outer div of the grid will have an id that matches this name.
    /// </summary>
    public string Name { get; private set; }

    /// <summary>
    ///     The <see cref="HtmlHelper" /> that is used to build the grid.
    /// </summary>
    public HtmlHelper HtmlHelper { get; private set; }

    /// <summary>
    ///     Sets the name of the <see cref="IGridBuilder{TModel}" />.
    /// </summary>
    /// <param name="name">The name that the <see cref="IGridBuilder{TModel}" /> should have.</param>
    /// <returns>An <see cref="IGridBuilder{TModel}" /> that is used to construct the grid.</returns>
    public IGridBuilder<TModel> WithName(string name)
    {
        Name = name;
        return this;
    }

    /// <summary>
    ///     Binds an column to the grid.
    /// </summary>
    /// <typeparam name="TItem">The type of the column on which to bind the items.</typeparam>
    /// <param name="propertySelector">The functional that will bind the control to the grid.</param>
    public void Bind<TItem>(Expression<Func<TModel, TItem>> propertySelector)
    {
        string name = ExpressionHelper.GetExpressionText(propertySelector);
        name = HtmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);

        ModelMetadata metadata =
            ModelMetadataProviders.Current.GetMetadataForProperty(() => Activator.CreateInstance<TModel>(),
                typeof(TModel), name);

        // Get's the name to display on the column in grid. The Display attribute is used if present, otherwise the name of the property is used.
        string displayName = string.IsNullOrEmpty(metadata.DisplayName)
            ? metadata.PropertyName
            : metadata.DisplayName;

        var items = (from TModel entity in HtmlHelper.ViewData.Model as IEnumerable select propertySelector.Compile().Invoke(entity).ToString()).ToList();

        properties.Add(displayName, items);
    }

    /// <summary>
    ///     Set the columns of the model that should be bound to grid.
    /// </summary>
    /// <param name="bindAllColumns">The action that will bind all the columns.</param>
    /// <returns>An <see cref="IGridBuilder{TModel}" /> that is used to construct the grid.</returns>
    public IGridBuilder<TModel> WithColumns(Action<IGridBuilder<TModel>> bindAllColumns)
    {
        bindAllColumns(this);
        return this;
    }

    #endregion

    #region IHtmlString Members

    /// <summary>
    ///     Returns an HTML-encoded string.
    /// </summary>
    /// <returns>Returns an HTML-encoded string.</returns>
    public string ToHtmlString()
    {
        var output = new StringBuilder();

        BaseElementBuilder parentBuilder = DivFactory.DivElement().WithCssClass("gridHolder v-scroll").WithId(Name);
        BaseElementBuilder headerBuilder = DivFactory.DivElement().WithCssClass("header");

        output.Append(parentBuilder.ToString(TagRenderMode.StartTag));
        output.Append(headerBuilder.ToString(TagRenderMode.StartTag));

        var index = 0;
        foreach (
           var propertyBuilder in
                properties.Select(
                    property =>
                        (index == 0)
                            ? DivFactory.DivElement().WithCssClass("inline").WithInnerHtml(property.Key)
                            : DivFactory.DivElement()
                                .WithCssClass("inline fixed right")
                                .WithInnerHtml(property.Key)))
        {
            output.Append(propertyBuilder);
            index += 1;
        }

        output.Append(headerBuilder.ToString(TagRenderMode.EndTag));

        for (int i = 0; i < properties.First().Value.Count(); i++)
        {
            BaseElementBuilder rowBuilder = DivFactory.DivElement().WithCssClass("row");
            output.Append(rowBuilder.ToString(TagRenderMode.StartTag));

            BaseElementBuilder iconBuilder = DivFactory.DivElement().WithCssClass("inline icon").WithInnerHtml("<img src=\"~/Resources/Icons/Grid/Pages/Page.png\" />");
            output.Append(iconBuilder.ToString(TagRenderMode.StartTag));
            output.Append(iconBuilder.ToString(TagRenderMode.EndTag));

            int loopIndex = 0;
            foreach (var propertyBuilder in properties)
            {
                var value = propertyBuilder.Value[i];
                BaseElementBuilder propertyConstructor = (loopIndex == 0)
                    ? DivFactory.DivElement().WithCssClass("inline").WithInnerHtml(value)
                    : DivFactory.DivElement().WithCssClass("inline fixed right").WithInnerHtml(value);

                loopIndex += 1;

                output.Append(propertyConstructor.ToString(TagRenderMode.Normal));
            }

            output.Append(rowBuilder.ToString(TagRenderMode.EndTag));
        }

        output.Append(parentBuilder.ToString(TagRenderMode.EndTag));

        return output.ToString();
    }

    #endregion
}
//
///的一种实现,用于构建网格。
/// 
///绑定到栅格的模型的类型。
公共类GridBuilder:IGridBuilder
{
#区域构造函数
/// 
///创建的新实例。
/// 
///用于渲染此对象的。
公共网格生成器(HtmlHelper HtmlHelper)
{
HtmlHelper=HtmlHelper;
属性=新字典();
}
#端区
#区域属性
/// 
///包含属性名称和所属显示名称的
///去那家酒店。
/// 
公共只读字典属性;
#端区
#区域构建器成员
/// 
///获取文件的名称。
///网格的外部div将具有与此名称匹配的id。
/// 
公共字符串名称{get;private set;}
/// 
///用于构建网格的。
/// 
公共HtmlHelper HtmlHelper{get;私有集;}
/// 
///设置文件的名称。
/// 
///应具有的名称。
///用于构造网格的。
带名称的公共IGridBuilder(字符串名称)
{
名称=名称;
归还这个;
}
/// 
///将列绑定到网格。
/// 
///要在其上绑定项的列的类型。
///将控件绑定到网格的函数。
公共void绑定(表达式属性选择器)
{
字符串名称=ExpressionHelper.GetExpressionText(propertySelector);
name=HtmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(名称);
模型元数据=
ModelMetadataProviders.Current.GetMetadataForProperty(()=>Activator.CreateInstance(),
类型(TModel),名称);
//Get是要在网格中的列上显示的名称。如果存在,则使用display属性,否则使用属性的名称。
string displayName=string.IsNullOrEmpty(metadata.displayName)
?metadata.PropertyName
:metadata.DisplayName;
var items=(来自HtmlHelper.ViewData.Model中的TModel实体,作为IEnumerable选择属性选择器.Compile().Invoke(entity.ToString()).ToList();
添加(显示名称、项目);
}
/// 
///设置应绑定到轴网的模型列。
/// 
///将绑定所有列的操作。
///用于构造网格的。
带列的公共IGridBuilder(操作bindAllColumns)
{
bindAllColumns(本);
归还这个;
}
#端区
#区域IHtmlString成员
/// 
///返回一个HTML编码的字符串。
/// 
///返回一个HTML编码的字符串。
公共字符串ToHtmlString()
{
var输出=新的StringBuilder();
BaseElementBuilder parentBuilder=DivFactory.DivElement(),带CSSClass(“gridHolder v-scroll”)。带ID(名称);
BaseElementBuilder headerBuilder=DivFactory.DivElement(),带CSSClass(“header”);
Append(parentBuilder.ToString(TagRenderMode.StartTag));
Append(headerBuilder.ToString(TagRenderMode.StartTag));
var指数=0;
弗雷奇(
中的var propertyBuilder
属性。选择(
属性=>
(索引==0)
?DivFactory.DivElement().WithCssClass(“内联”).WithInnerHtml(property.Key)
:DivFactory.DivElement()
.带CSSClass(“内联固定右侧”)
.WithInnerHtml(property.Key)))
{
Append(propertyBuilder);
指数+=1;
// Get the type in the collection
Type type = GetCollectionType(collection); // See below
// Get the metadata of the type in the collection
ModelMetadata typeMetadata = ModelMetadataProviders.Current
  .GetMetadataForType(null, type);
foreach (var item in collection)
{
  ModelMetadata itemMetadata = ModelMetadataProviders
    .Current.GetMetadataForType(() => item, type);
  // Use itemMetadata.Properties to generate the columns 
private static Type GetCollectionType(IEnumerable collection)
{
  Type type = collection.GetType();
  if (type.IsGenericType)
  {
    return type.GetInterfaces().Where(t => t.IsGenericType)
      .Where(t => t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
      .Single().GetGenericArguments().Last();
  }
  else if (collection.GetType().IsArray)
  {
    return type.GetElementType();
  }
  else
  {
        // Who knows?
        return null;
   }
}
public void Bind<TItem>(Expression<Func<TModel, TItem>> propertySelector)
{
  string name = ExpressionHelper.GetExpressionText(propertySelector);
  name = HtmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
  IEnumerable collection = HtmlHelper.ViewData.Model as IEnumerable;
  foreach (var item in collection)
  {
    ModelMetadata modelMetadata = ModelMetadataProviders.Current
      .GetMetadataForType(() => item, item.GetType())
      .Properties.First(m => m.PropertyName == name);
    string displayName = modelMetadata.GetDisplayName();
    if (!properties.ContainsKey(displayName))
    {
      properties[displayName] = new List<string>();
    }
    // Take into account display format and null values
    string format = modelMetadata.DisplayFormatString ?? "{0}";
    properties[displayName].Add(string.Format(format, 
      modelMetadata.Model ??  modelMetadata.NullDisplayText));     
  }
}