The elegant Action Syntax in the MVCContrib Grid gives us the Empty()
method. However, the default behavior of MvcContrib.UI.Grid.GridRenderer<T>.RenderHeader()
is to hide the table column headers when the grid is empty. Is there a way to show headers when data is not present that does not require a major refactoring?
Now I have heard of hiding the headers by default and hard-coding something but this is not cool to me.
By the way, this is what is happening under the hood (in MvcContrib.UI.Grid.GridRenderer<T>
):
protected virtual bool RenderHeader()
{
//No items - do not render a header.
if(! ShouldRenderHeader()) return false;
RenderHeadStart();
foreach(var column in VisibleColumns())
{
//Allow for custom header overrides.
if(column.CustomHeaderRenderer != null)
{
column.CustomHeaderRenderer(new RenderingContext(Writer, Context, _engines));
}
else
{
RenderHeaderCellStart(column);
RenderHeaderText(column);
RenderHeaderCellEnd();
}
}
RenderHeadEnd();
return true;
}
protected virtual bool ShouldRenderHeader()
{
return !IsDataSourceEmpty();
}
protected bool IsDataSourceEmpty()
{
return DataSource == null || !DataSource.Any();
}
In your custom Grid Renderer (subclass GridRenderer<T>
) use overrides like these:
/// <summary>
/// Renders the <c>table</c> header.
/// </summary>
/// <returns>
/// Returns the negative of the results
/// of <see cref="GridRenderer<T>.IsDataSourceEmpty"/>.
/// </returns>
/// <remarks>
/// The return value of <see cref="GridRenderer<T>.IsDataSourceEmpty"/>
/// in this override has no effect on whether the Grid header is rendered.
///
/// However, this return value is used
/// by <see cref="GridRenderer<T>.Render"/>
/// to run <see cref="GridRenderer<T>.RenderItems"/>
/// or <see cref="GridRenderer<T>.RenderEmpty"/>.
/// </remarks>
protected override bool RenderHeader()
{
RenderHeadStart();
foreach(var column in VisibleColumns())
{
//Allow for custom header overrides.
if(column.CustomHeaderRenderer != null)
{
column.CustomHeaderRenderer(new RenderingContext(Writer, Context, _engines));
}
else
{
RenderHeaderCellStart(column);
RenderHeaderText(column);
RenderHeaderCellEnd();
}
}
RenderHeadEnd();
return !base.IsDataSourceEmpty();
}
…
protected override void RenderEmpty()
{
RenderBodyStart();
WriteNoRecordsAvailable(base.Writer, this._numberOfTableColumns);
RenderBodyEnd();
}
Note that WriteNoRecordsAvailable()
is my custom method so it can be ignored.
Finally:
/// <summary>
/// This private member is duplicated
/// in order to override <see cref="GridRenderer<T>.RenderHeader"/>.
/// </summary>
readonly ViewEngineCollection _engines;
…
/// <summary>
/// Initializes a new instance of the <see cref="CrmHtmlTableGridRenderer<T>"/> class.
/// </summary>
/// <param name="engines">The engines.</param>
public CrmHtmlTableGridRenderer(ViewEngineCollection engines)
: base(engines)
{
_engines = engines;
}