0

I'm trying to make an editable table. I have a dynamic table, columns can be made visible or invisible. I have an extra column with an edit button. When I hit this I do an Ajax call to get an editable version of the row.

My viewmodel:

public class List: IDynamicGridDataModel<View>
{
    public List()
    {
        ColumnOptions = new ColumnOptions();
        ColumnOptions.SelectedColumns = new List<string>() { "Address", "ZipCode", "City", "Country" };
        ColumnOptions.DisabledColumns = new List<string>() { "Id" };

        Items = new List<View>();
    }

    #region IDynamicGridDataModel<View> Members

    public ColumnOptions ColumnOptions { get; set; }
    public GridModel<View> GridModel { get; set; }
    public IEnumerable<View> Items { get; set; }

    #endregion
}

Where the items are:

public class View
{
    public long Id { get; set; }
    public string Address { get; set; }
    public string ZipCode { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
}

I have the following extension to create the table row:

public static MvcHtmlString EditorRowFor<TModel, TRow>(this HtmlHelper<TModel> html, Expression<Func<TModel,TRow>> expression, IEnumerable<string> selectedColumns)
{
    var metadataProvider = new DataAnnotationsModelMetadataProvider();
    var stringBuilder = new StringBuilder();

    stringBuilder.Append("<tr>");

    foreach (var column in selectedColumns)
    {
        var entityParam = Expression.Parameter(expression.ReturnType);

        var columnLambda = Expression.Lambda(Expression.Property(entityParam, typeof(TRow), column));

        var selectCall = Expression.Call(typeof(Queryable),
                                         "Select",
                                         new Type[] { typeof(TModel), columnLambda.Body.Type },
                                         expression,
                                         columnLambda);

       html.EditorCellFor(selectCall);

        stringBuilder.AppendLine("</td>");
    }

    stringBuilder.AppendLine("</tr>");
    return new MvcHtmlString(stringBuilder.ToString());
}

This function is called from my view like this:

@Html.EditorRowFor(m => m.Items.Single(), Model.ColumnOptions.SelectedColumns);

The EditorCellFor method signature:

public static MvcHtmlString EditorCellFor<TModel, TItem>(this HtmlHelper<TModel> html, Expression<Func<TModel, TItem>> expression)

My current problem is with the creation of the selectCall. I want to make an Expression for the Lambda expression:

m => m.Items.Single().Select(i => i.Address)

I get the following error:

No generic method 'Select' on type 'System.Linq.Queryable' is compatible with 
the supplied type arguments and arguments. No type arguments should be 
provided if the method is non-generic.

Most of the code surrounding that part I saw on http://www.hanselman.com/blog/TheWeeklySourceCode47ASPNET35DynamicDataFilterRepeatersAndDynamicLinqQueryGeneration.aspx.

I've been searching for the problem the entire morning but no luck so far.

Kasper Cottaar
  • 462
  • 3
  • 14

1 Answers1

0

Once you've called Single, you only get a single value anyway - the point of Select is to project a sequence of values.

So either use:

m => m.Items.Single().Address

or

m => m.Items.Select(i => i.Address).Single()
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Good point. But how do I get these in the form of a Linq Expression when I have m => m.Items.Single()? It must be in a Linq Expression because I want to pass it to Html.EditorFor<>. – Kasper Cottaar Jul 19 '12 at 12:40
  • 1
    Looks like you should use `m.Items.Take(1).Select(...)` – Gert Arnold Jul 19 '12 at 14:00