Custom MVC WebGrid Demo 1 · Server Code


@model MyMvc4App.Controllers.FilteredSortedPagedLocation
@using System.Text
@using System.Text.RegularExpressions

@{
    //ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout_WebGridDemo1.cshtml";

    // create a WebGrid but don't bind to data yet
    WebGrid grid = new WebGrid(
        //source: Model
        source: null
        , defaultSort: "Location1"
        , rowsPerPage: Model.FilterSortPageInfo.PageSize
        //,canPage: false
        , sortDirectionFieldName: "sortDir"
    );

    // bind data here so we can set total row count
    //  and disable automatic sorting and paging
    grid.Bind(
        source: Model.ProductList
        , rowCount: Model.FilterSortPageInfo.TotalRecords
        , autoSortAndPage: false
    );    
}

<h2>Adventure Works Products</h2>

<form action="~/WebGridDemo1" method="get">
    <!-- the following are the required data to send to the server via query string 
         they are populated before submitting the form via JavaScript
    -->
    <input type="hidden" name="sort" value="@Model.FilterSortPageInfo.Sort"/>
    <input type="hidden" name="sortDir" value="@Model.FilterSortPageInfo.SortDir" />
    <input type="hidden" name="page" value="@Model.FilterSortPageInfo.Page" />

    <input type="hidden" name="newFilter" value="false" />
    <input type="hidden" name="clearFilters" value="false" />
    <input type="hidden" name="filters" value="@Model.FilterSortPageInfo.Filters" />
</form>

@{
    var filters = Json.Decode(Model.FilterSortPageInfo.Filters, typeof(List<MyMvc4App.Filter>));
    var filtersString = "";
    foreach (MyMvc4App.Filter filter in filters)
    {
        filtersString += ", " + filter.Field + " (" + filter.Value + ")";
    }
    if (filtersString.Length > 0) 
    {
        filtersString = filtersString.Substring(2);
    }
}

<div id="divFilter">
    <fieldset>
        <legend>Filter By</legend>
        <table>
            <tr>
                <td><label for="selectFilterField">Field: </label></td>
                <td>
                    <select id="selectFilterField" name="selectFilterField">
                        <!-- option values are appended with input type after ":" 
                              in order to validate input based on type
                        -->
                        <option value=""></option>
                        <option value="ProdNum:text">Product Number</option>
                        <option value="Name:text">Name</option>
                        <option value="Color:text">Color</option>
                        <option value="Size:text">Size</option>
                        <option value="ProdCat:text">Product Category</option>
                        <option value="ProdModel:text">Product Model</option>
                    </select>
                </td>
                <td><label for="inputFilterValue">Value: </label></td>
                <td><input id="inputFilterValue" name="inputFilterValue" type="text" /></td>
                <td><input type="button" value="Apply Filter" id="buttonApplyFilter" /></td>
                <td><input type="button" value="Clear Filters" id="buttonClearFilters" @(filtersString.Length == -1 ? "disabled=disabled" : "") /></td>
            </tr>
        </table>
    </fieldset>
</div>

<!-- display filter, sort, and page settings for debugging use only -->
<div class="debug">
Filter: @filtersString <br />
Sort: @Model.FilterSortPageInfo.Sort (@Model.FilterSortPageInfo.SortDir) <br />
Page: @Model.FilterSortPageInfo.Page
</div>

<div id="divGrid">
@{
    WebGridColumn[] columns =
        grid.Columns(
            grid.Column("ProductNumber", "Product Number"),
            grid.Column("Name", "Name"),
            grid.Column("Color", "Color"),
            grid.Column("StandardCost", "Standard Cost"),
            grid.Column("ListPrice", "List Price"),
            grid.Column("Size", "Size"),
            grid.Column("Weight", "Weight"),
            grid.Column("ProductCategory.Name", "Product Category"),
            grid.Column("ProductModel.Name", "Product Model"),
            grid.Column(
                format: item => new HtmlString(
                    Html.ActionLink("Details", "Details", new { id = item.ProductID }).ToString()
                )
            )
        );

    // add asc/desc indicator character at the end of the sort column header
    string sortDirChar = Model.FilterSortPageInfo.SortDir.ToUpper().Equals("DESC") ? "↓" : "↑";
    WebGridColumn sortCol = columns.First(c => c.ColumnName == Model.FilterSortPageInfo.Sort);
    sortCol.Header = sortCol.Header + sortDirChar;
            
    string tableHTML =
        grid.GetHtml(
            columns: columns
            ,mode: WebGridPagerModes.All
        ).ToString();

    
    // assemble the filters HTML which will be added at the end of the paging control
    string filtersHTML = String.Empty;
    if (filtersString.Length > 0)
    {
        filtersHTML = String.Format("<span>Filtered: {0}</span>", filtersString);
    }
    
    if (grid.TotalRowCount <= grid.RowsPerPage && filtersHTML.Length > 0)
    {
        // if there is no paging control displayed because there is only 1 page of data to display,
        //  then we have to add a <tfoot> tag to the end of the grid table and put the filters HTML inside it
        tableHTML = tableHTML.Replace("</table>",
            String.Format("<tfoot><tr><td colspan='{0}'>{1}</td></tr></tfoot></table>", columns.Count(), filtersHTML));
    }
    else
    {
        // if there is a paging control, then add the filters HTML at the end of the paging control
        
        // and also wrap the paging control's current page number in a <a> tag with id="currPageNo"
        string currPageNoHtml = String.Format("<a id='currPageNo'>{0}</a>", Model.FilterSortPageInfo.Page);

        string pattern = String.Format("<tfoot>(.*)(\\s*{0}\\s)(.*)</td>.*</tr>.*</tfoot>", Model.FilterSortPageInfo.Page.ToString());
        Regex regEx = new Regex(pattern, RegexOptions.Singleline);
        tableHTML = regEx.Replace(tableHTML, String.Format("<tfoot>$1 {0} $3{1}</td></tr></tfoot>", currPageNoHtml, filtersHTML));
    }
        
}
@Html.Raw(tableHTML)
</div>


@section styles{
    <style>
        .debug
        {
            display: none;
        }
        
        #divFilter
        {
            margin: 30px 0px 30px 0px;
        }
        
        #divFilter fieldset
        {
            /*border: 2px groove threedface;*/
            border: 1px solid #787878;
            /*border-radius: 2px;*/
            margin: 6px 0px 6px 0px;
            padding: 0em 0.75em 0.625em 0.75em;
        }
        
        #divFilter fieldset legend
        {
            display: block;
            font-weight: 600; 
        }
        
        #divFilter table
        {
            margin-top: 0px;
            margin-left: 3px;
        }

        /* filter by field and value label controls */
        #divFilter label
        {
            font-size: 1em;
            font-weight: normal;
            margin-right: 0em;
        }
        
        /* filter by field dropdown control */
        #divFilter select
        {
            /*width: 300px;*/
            padding: 5px;
            border: 1px solid #e2e2e2;
        }

        /* filter by input controls */
        #divFilter input
        {
            font-size: 1em;
            width: auto;
        }

        /* filter by disabled input button controls */
        #divFilter input[type="button"]:disabled
        {
            cursor: initial;
            color: GrayText;
        }

        #divGrid thead tr
        {
            border-bottom: 1px solid #787878;
        }
                
        #divGrid thead th
        {
            padding-right: 15px;
            /*padding-bottom: 5px;*/
        }
        
        #divGrid tfoot td
        {
            /*font-weight: bold;*/
            /*font-size: 1.25em;*/
            padding-top: 15px;
        }
       
        /* paging links at webgrid footer */
        #divGrid tfoot a
        {
            /*font-weight: normal;*/
            /*font-size: 1.0em;*/
            text-decoration: none;
            border: 1px solid #787878;
            /*border-radius: 2px;*/
            /*float: left;*/
            /*margin-left: -1px;*/
        }
        
        /* current page number at webgrid footer */
        #divGrid tfoot a[id="currPageNo"]
        {
            background-color: #c7d1d6;
        }

        /* filters text at webgrid footer */
        #divGrid tfoot span
        {
            /*font-size: 0.90em;*/
            font-style: italic;
        }

        /* filters text at webgrid footer when there is paging control */
        #divGrid tfoot span:not(:only-child)
        {
            margin-left: 10px;
        }

    </style>
}


@section scripts{
    <script src="../../Scripts/json2.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function () {

            // add a utility method to jQuery that will return the value of a parameter in a URL
            $.urlParam = function (name, url) {
                var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(url);
                if (results == null) {
                    return null;
                }
                else {
                    return results[1] || 0;
                }
            }

            // bypass the webgrid's default column sort click function
            // instead do a form submit
            $("#divGrid thead a").click(function (evt) {
                // get sort and sortdir URL parameters
                var url = $(this).attr("href")
                var sort = $.urlParam("sort", url);
                var sortDir = $.urlParam("sortDir", url);

                $("form input[name='sort']").val(sort);
                $("form input[name='sortDir']").val(sortDir);
                $("form input[name='page']").val("1");

                $("form").submit();

                evt.preventDefault();
            });

            // bypass the webgrid's default footer page click function
            // instead do a form submit
            $("#divGrid tfoot a").click(function (evt) {
                // get page parameter
                var url = $(this).attr("href")

                // make sure href attribute is present
                if (url) {
                    var page = $.urlParam("page", url);

                    $("form input[name='page']").val(page);

                    $("form").submit();

                    evt.preventDefault();
                }
            });


            // add click event handler for the apply filter button
            $("#buttonApplyFilter").click(function (evt) {
                var filterField = $("#selectFilterField option:selected").text();
                var filterValue = $("#inputFilterValue").val();

                var filters = JSON.parse($("form input[name='filters']").val());
                filters.push({ Field: filterField, Value: filterValue });

                $("form input[name='filters']").val(JSON.stringify(filters));
                $("form input[name='newFilter']").val('true');

                $("form").submit();

                evt.preventDefault();
            });

            // add click event handler for the clear filters button
            $("#buttonClearFilters").click(function (evt) {
                $("form input[name='clearFilters']").val('true');

                $("form").submit();

                evt.preventDefault();
            });

        });

    </script>
}