Read only grid without paging

Computed columns whose value depends on several fields may be defined by adding a column with no asp-for, ie not connected to any property, but with just a name.

Computed columns MUST have a custom display template that defines the way they combine the data item properties. Clearly they can't have an edit template, so they are defined readonly. This way, the display template is used also if the row is rendered in edit mode. Since the column is not specific to any property the custom template receives the full item model in Html.Item<T>().In the example below we removed the price and currency columns, to add a computed column that combine them.

Name Price Av
16G Tablet 400.00$
1T High speed 120.00
1T SSD 200.00
3D Glasses 400.00$
color laser printer 400.00$
ink jet printer 100.00$
laptop 1200.00
<grid asp-for="Products.Data"
      type="Immediate"
      all-properties="true"
      mvc-controller="typeof(LiveExamples.Controllers.GridsController)"
      row-id="readonly-example"
      operations="user => Functionalities.ReadOnly | Functionalities.ShowDetail"
      class="table table-condensed table-bordered">
    <column asp-for="Products.Data.Element().Price" remove="true" />
    <column asp-for="Products.Data.Element().ChosenCurrency" remove="true" />
    <column name="fullprice"
            title="Price" priority="300" readonly="true">
        <asp-template type="Display">
            @{{
                    var Model = Html.Item<SimpleProductViewModel>();
                    <span>@Model.Price</span>@getEnumDisplayName(Model.ChosenCurrency)
                }}
        </asp-template>
    </column>
</grid>
/*
 DetailWidthsAsString in ColumnLayout specifies percentage width 
 for different device screen widths, while WidthsAsString
 percentage width when shown in-line within a collection control.
 Oder specify the order columns are rendered. Higher Order come first.
 All setting, included Display/Name may be overriden by providing
 a column definition TagHelper within the control definition.
*/
public class SimpleProductViewModel 
{
    public int? Id { getset; }
    [MaxLength(128)]
    [ColumnLayout(DetailWidthsAsString = "100 50")]
    [Required]
    [Display(Name = "Name", Order = 400)]
    public string Name { getset; }
    [ColumnLayout(DetailWidthsAsString = "60 30")]
    [Display(Name = "Price", Order = 300)]
    public decimal Price { getset; }
    [Display(Name = "Cur", Order = 280)]
    [ColumnLayout(WidthsAsString = "10", DetailWidthsAsString = "40 20")]
    public Currency ChosenCurrency { getset; }
    [ColumnLayout(DetailWidthsAsString = "20")]
    [Display(Name = "Av", Order = 230)]
    public bool Available { getset; }
}   
 
public class SimpleProductViewModelDetailSimpleProductViewModel
{
    [MaxLength(256)]
    [Display(Name = "Description", Order = 100)]
    [ColumnLayout(DetailWidthsAsString = "80")]
    [DisplayFormat(NullDisplayText = "no description available")]
    public string Description { getset; }
}
public async Task<IActionResult> ReadonlyComputed()
{
    var model = new SimpleProductlistViewModel
    {
        Products = await Repository.GetPage<SimpleProductViewModel>(
        null,
        q => q.OrderBy(m => m.Name),
        1, 20)
    };
    return View(model);
}

Fork me on GitHub