2
votes

What I am trying to achieve is hard to explain, so please let me know if I can provide more information. I have a feeling that I am trying to use WebGrids beyond their means, so if anyone has any open source alternatives that would do what I am trying, that would also be helpful.

I need to build a WebGrid from the ground up, because the content returned to it (columns and values) changes depending on other criteria on my form. I have this working in a few simple lines of code in a Table, but I wanted to use WebGrid for the styling, sorting and paging.

@model DocumentSearchViewModel

@if ((this.Model != null) && (this.Model.SearchResults != null) &&     (this.Model.SearchResults.Count() > 0))
{ 
    <table>
        <thead>
            <tr>
                <th>Document</th>
                @foreach (var metadata in this.Model.SearchResults.Metadata)
                {
                    <th>
                        @metadata.InstanceFieldName
                    </th>
                }
            </tr>
        </thead>
        <tbody>
            @foreach (var document in this.Model.SearchResults)
            {
                <tr>
                <td>
                    @Html.ActionLink(document.Id.ToString(), "Details", new { id = document.Id })
                </td>
                    @foreach (var metadata in document.Metadata)
                    {
                        <td>
                            @metadata.Value
                        </td>
                    }
                </tr>
            }
        </tbody>
    </table>
}

So to explain the model structure, The SearchResults has an IEnumerable<MetadataModel>, and this MetadataModel has properties of InstanceFieldName and Value. When a search is performed, every result will always have the same number of Metadata, and the same InstanceFieldNames, but different values, however a quick change of a field on the form, and a new search could return a new set of results (Again with the same set of Metadata as each other, but different to the first set of results)

The columns of the grid correspond to the Metadata InstanceFieldName, and the content the Value.

So I have made my best attempt using WebGrid, but the best I can get is a grid with the right column headers, and the right number of rows, the columns have the right data, but each row is the same (copied from the last row).

@{
var grid = new WebGrid(canPage: true, canSort: true, rowsPerPage: Model.PageSize,     sortFieldName: Model.Sort, sortDirectionFieldName: Model.SortDir);
grid.Bind(Model.SearchResults, rowCount: Model.DocumentCount);
List<WebGridColumn> cols = new List<WebGridColumn>();
foreach(var metadata in Model.SearchResults.Select(r => r.Metadata).FirstOrDefault())
{
    var col = new WebGridColumn();
    col.ColumnName = metadata.InstanceFieldName;
    col.Header = metadata.InstanceFieldHeader;
    col.Style = "gridRow";
    col.CanSort = true;
    cols.Add(col);
}

foreach (var result in Model.SearchResults)
{        
    foreach (var col in cols)
    {
        var metadataValue = result.Metadata.Single(m => m.InstanceFieldName == col.ColumnName).Value;
        col.Format = (item) => @Html.Raw("<text>" + metadataValue + "</text>");
    }
}
}

@if ((this.Model != null) && (this.Model.SearchResults != null) && (this.Model.SearchResults.Count() > 0))
{   
    @grid.GetHtml(htmlAttributes: new { id = "documentGrid" }, rowStyle: "gridRow", alternatingRowStyle: "gridRowAlt", columns: cols)
}

What I'm trying to work out is how and if possible to generate the columns first, and then populate the rows into these columns.

Any help is really appreciated, thanks, Mark

1

1 Answers

0
votes

You are feeding the rows with the same value, you should change the Format:

col.Format = (item) => @Html.Raw(item.metadataValue);