Binding

Use the following steps to display data within the Grid View control:

  1. Create a column for each data field whose data you want to display.
  2. Call the Bind method with the data source object as a parameter.

Some operations (e.g., editing and grouping) also require a key field to be specified using the KeyFieldName method.

You can initialize grid columns in one of the following ways:

Product Name Quantity Per Unit Unit Price Units On Order Total
Chai10 boxes x 20 bags180$0.00
Chang24 - 12 oz bottles1940$760.00
Aniseed Syrup12 - 550 ml bottles1070$700.00
Chef Anton's Cajun Seasoning48 - 6 oz jars220$0.00
Chef Anton's Gumbo Mix36 boxes210$0.00
Grandma's Boysenberry Spread12 - 8 oz jars250$0.00
Uncle Bob's Organic Dried Pears12 - 1 lb pkgs.300$0.00
Northwoods Cranberry Sauce12 - 12 oz jars400$0.00
Mishi Kobe Niku18 - 500 g pkgs.970$0.00
Ikura12 - 200 ml jars310$0.00
@model IEnumerable
@(Html.DevExpress()
    .BootstrapGridView<DevExpress.AspNetCore.DemoModels.SalesProduct>("bindingGrid")
    .KeyFieldName(m => m.ProductID)
    .Columns(columns => {
        columns.Add(m => m.ProductName);
        columns.Add(m => m.QuantityPerUnit);
        columns.Add()
            .FieldName("UnitPrice");
        columns.Add()
            .FieldName("UnitsOnOrder");
        columns.AddTextColumn()
            .FieldName("Total")
            .UnboundType(UnboundColumnType.Decimal)
            .UnboundExpression("UnitsOnOrder * UnitPrice")
            .PropertiesTextEdit(properties => properties
                .DisplayFormatString("c"));
    })
    .Routes(routes => routes
        .MapRoute(r => r
            .Action("Binding")
            .Controller("GridView")))
    .Bind(Model))
using System;
using Microsoft.AspNetCore.Mvc;
using DevExpress.AspNetCore.DemoModels;
namespace DevExpress.AspNetCore.Demos {
    public partial class GridViewController : Controller {
        public IActionResult Binding() {
            return PartialView("DataBinding/Binding", SimpleBindingContext.Products);
        }
    }
}
using System.ComponentModel.DataAnnotations;

namespace DevExpress.AspNetCore.DemoModels {
    public class SalesProduct {
        [Key]
        public int ProductID { get; set; }
        public string ProductName { get; set; }
        public short? UnitsOnOrder { get; set; }
        public short? UnitsInStock { get; set; }
        public decimal? UnitPrice { get; set; }
        public string QuantityPerUnit { get; set; }
    }
}

Binding to Large Database using XPO

The Grid View control supports data binding in server mode, which is designed to work with large datasets. In this binding mode, the data-aware operations (sorting, filtering, grouping, etc.) are performed on the database server, which significantly improves the Grid View's speed and responsiveness.

In this demo, the BindToXPO method is used to establish server-mode data binding via DevExpress eXpress Persistent Objects for .NET (XPO) ORM. Refer to the Getting Started with .NET Core article to learn more about XPO.

Drag a column header here to group by that column
From Subject Sent Has Attachment Size
 
Bert ParkinsEmail Attachments. Is it possible to add multiple attachments? I haven't found a way to do this.4/3/2016 5.74 KB
Tom HamlettPayables Due Calculator is ready for testing.3/8/2016 45.65 KB
Tom HamlettEmail Attachments. Is it possible to add multiple attachments? I haven't found a way to do this.2/26/2016 180.06 KB
Ray ShipmanIntegrating Developer Express MasterView control into an Accounting System.2/21/2016200.6 KB
Tom HamlettEmail System. What library are we going to use?3/31/2016 252.16 KB
Dave MurrelMain Menu: Add a File menu. File menu item is missing.3/12/2016270.49 KB
Ryan FischerReceivables Calculator. Where can I find the complete specs?3/5/2016209.34 KB
Carl LucasPayables Due Calculator is ready for testing.2/28/2016 189.17 KB
Brad BarnesReceivables Calculator. Where can I find the complete specs?3/9/2016141.5 KB
Carl LucasDrag & Drop operations are not available in the scheduler module.4/6/2016 226.69 KB
@model XPQuery<XPEmail>
@(Html.DevExpress()
      .BootstrapGridView<XPEmail>("gridWithXPO")
      .KeyFieldName(k => k.ID)
      .Columns(columns => {
          columns.Add(c => c.From);
          columns.Add(c => c.Subject);
          columns
              .Add(c => c.Sent)
              .Width(220);
          columns
              .Add(c => c.HasAttachment)
              .Width(150);
          columns
              .Add(c => c.Size)
              .Settings(settings => settings.AllowAutoFilter(false));
      })
      .TotalSummary(summary => summary
          .Add(s => s.Size)
          .SummaryType(SummaryItemType.Sum))
      .GroupSummary(summary => summary
          .Add()
          .SummaryType(SummaryItemType.Count))
      .Settings(settings => settings
          .ShowFilterRow(true)
          .ShowFilterRowMenu(true)
          .ShowGroupPanel(true)
          .ShowFooter(true))
      .Routes(routes => routes
          .MapRoute(r => r
              .Action("BindingToXPOPartial")
              .Controller("GridView")))
      .SettingsPager(pager => pager
          .NumericButtonCount(4)
          .PageSizeItemSettings(pageSize => pageSize
              .Visible(true)
              .Items("10", "20", "50")))
      .CssClassesPager(pager => pager
          .PageNumber("d-none d-xl-block")
          .Ellipsis("d-none d-xl-block")
          .Summary("d-none d-md-block"))
      .ClientSideEvents(events => events
          .Init("onGridWithXPOInit")
          .BeginCallback("onGridWithXPOBeginCallback")
          .EndCallback("onGridWithXPOEndCallback"))
      .OnCustomColumnDisplayText((grid, e) => {
          if(e.Column.FieldName == "Size")
              e.DisplayText = FormatByteSize(e.Value);
      })
      .OnSummaryDisplayText((grid, e) => {
          if(e.Item.FieldName == "Size")
              e.Text = $"Sum = {FormatByteSize(e.Value)}";
      })
      .BindToXPO(Model))
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc;
namespace DevExpress.AspNetCore.Demos {
    public partial class GridViewController : Controller {
        protected LargeDatabaseUnitOfWork LargeDatabaseUnitOfWork => HttpContext.RequestServices.GetService<LargeDatabaseUnitOfWork>();
        public IActionResult BindingToXPO() {
            if(!EmailTableGenerator.IsReady(HttpContext.RequestServices))
                return ViewComponent("DatabaseGenerator", new { key = "XPO", modelTypeName = "Email" });
            return PartialView("DataBinding/BindingToXPO", LargeDatabaseUnitOfWork.Emails);
        }
        public IActionResult BindingToXPOPartial() {
            return PartialView("DataBinding/BindingToXPOPartial", LargeDatabaseUnitOfWork.Emails);
        }
    }
}
using System;
using DevExpress.Xpo;
using DevExpress.Xpo.DB;
using DevExpress.Xpo.Metadata;
using Microsoft.Extensions.DependencyInjection;

namespace DevExpress.AspNetCore.Demos {
    public class LargeDatabaseUnitOfWork : UnitOfWork {
        public LargeDatabaseUnitOfWork(IDataLayer dataLayer)
            : base(dataLayer) {
        }

        public XPQuery<XPEmail> Emails => this.Query<XPEmail>();
    }

    [Persistent("Emails")]
    public class XPEmail : XPLiteObject {
        public XPEmail(Session session)
            : base(session) {
        }

        [Key(true)]
        public int ID {
            get => GetPropertyValue<int>("ID");
            set => SetPropertyValue("ID", value);
        }
        [Size(100)]
        public string Subject {
            get => GetPropertyValue<string>("Subject");
            set => SetPropertyValue("Subject", value);
        }
        [Size(32)]
        public string From {
            get => GetPropertyValue<string>("From");
            set => SetPropertyValue("From", value);
        }
        public DateTime Sent {
            get => GetPropertyValue<DateTime>("Sent");
            set => SetPropertyValue("Sent", value);
        }
        public long Size {
            get => GetPropertyValue<long>("Size");
            set => SetPropertyValue("Size", value);
        }
        public bool HasAttachment {
            get => GetPropertyValue<bool>("HasAttachment");
            set => SetPropertyValue("HasAttachment", value);
        }
    }

    public static class XpoServiceExtensions {
        static readonly Type[] EntityTypes = new Type[] { typeof(XPEmail) };
        static ReflectionDictionary ReflectionDictionary = new ReflectionDictionary();

        static XpoServiceExtensions() {
            ReflectionDictionary.GetDataStoreSchema(EntityTypes);
        }

        public static IServiceCollection AddLargeDatabaseUnitOfWork(this IServiceCollection services, string connectionString) {
            services.AddSingleton<LargeDatabaseDataLayer>(serviceProvider => {
                return CreatePooledDataLayer(connectionString);
            });
            services.AddScoped<LargeDatabaseUnitOfWork>(serviceProvider => {
                var dataLayer = serviceProvider.GetService<LargeDatabaseDataLayer>();
                return new LargeDatabaseUnitOfWork(dataLayer);
            });
            return services;
        }
        static LargeDatabaseDataLayer CreatePooledDataLayer(string connectionString) {
            using(var updateDataLayer = XpoDefault.GetDataLayer(connectionString, ReflectionDictionary, AutoCreateOption.DatabaseAndSchema)) {
                updateDataLayer.UpdateSchema(false, ReflectionDictionary.CollectClassInfos(EntityTypes));
            }

            var dataStore = XpoDefault.GetConnectionProvider(XpoDefault.GetConnectionPoolString(connectionString), AutoCreateOption.SchemaAlreadyExists);
            return new LargeDatabaseDataLayer(ReflectionDictionary, dataStore);
        }
    }
    public class LargeDatabaseDataLayer : ThreadSafeDataLayer {
        public LargeDatabaseDataLayer(XPDictionary dictionary, IDataStore provider)
            : base(dictionary, provider) {
        }
    }
}

Binding to Large Database using EF Core

You can use Entity Framework (EF) Core as an ORM to bind the Grid View control to a large dataset in server mode. Pass a Querable collection to the BindToLINQ method to establish data binding via EF Core.

Note. The current EF Core version (2.0) always evaluates the GroupBy LINQ operator in memory instead of generating the SQL GROUP BY clause. As a result, Grid View's data shaping features which use this operator (grouping, summaries, etc.) perform poorly with large amounts of data. According to the Entity Framework Core 2.1 Roadmap article, this issue should be resolved in EF Core framework versions 2.1 and later.

From Subject Sent Has Attachment Size
 
Bert ParkinsEmail Attachments. Is it possible to add multiple attachments? I haven't found a way to do this.4/3/2016 5874
Tom HamlettPayables Due Calculator is ready for testing.3/8/2016 46749
Tom HamlettEmail Attachments. Is it possible to add multiple attachments? I haven't found a way to do this.2/26/2016 184383
Ray ShipmanIntegrating Developer Express MasterView control into an Accounting System.2/21/2016205415
Tom HamlettEmail System. What library are we going to use?3/31/2016 258211
Dave MurrelMain Menu: Add a File menu. File menu item is missing.3/12/2016276977
Ryan FischerReceivables Calculator. Where can I find the complete specs?3/5/2016214367
Carl LucasPayables Due Calculator is ready for testing.2/28/2016 193712
Brad BarnesReceivables Calculator. Where can I find the complete specs?3/9/2016144899
Carl LucasDrag & Drop operations are not available in the scheduler module.4/6/2016 232127
@model IQueryable<Email>
@(Html.DevExpress()
      .BootstrapGridView<Email>("gridWithLargeDatabase")
      .KeyFieldName(k => k.ID)
      .Columns(columns => {
          columns.Add(c => c.From);
          columns.Add(c => c.Subject);
          columns
              .Add(c => c.Sent)
              .Width(220);
          columns
              .Add(c => c.HasAttachment)
              .Width(150);
          columns
              .Add(c => c.Size)
              .Settings(settings => settings.AllowAutoFilter(false));
      })
      .Settings(settings => settings
          .ShowFilterRow(true)
          .ShowFilterRowMenu(true))
      .Routes(routes => routes
          .MapRoute(r => r
              .Action("BindingToEFCorePartial")
              .Controller("GridView")))
      .SettingsPager(pager => pager
          .NumericButtonCount(4)
          .PageSizeItemSettings(pageSize => pageSize
              .Visible(true)
              .Items("10", "20", "50")))
      .CssClassesPager(pager => pager
          .PageNumber("d-none d-xl-block")
          .Ellipsis("d-none d-xl-block")
          .Summary("d-none d-md-block"))
      .ClientSideEvents(events => events
          .Init("onGridWithEFCoreInit")
          .BeginCallback("onGridWithEFCoreBeginCallback")
          .EndCallback("onGridWithEFCoreEndCallback"))
      .BindToLINQ(Model))
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
namespace DevExpress.AspNetCore.Demos {
    public partial class GridViewController : Controller {
        protected LargeDatabaseContext LargeDatabaseContext => HttpContext.RequestServices.GetService<LargeDatabaseContext>();
        public IActionResult BindingToEFCore() {
            if(!EmailTableGenerator.IsReady(HttpContext.RequestServices))
                return ViewComponent("DatabaseGenerator", new { key = "EFCore", modelTypeName = "Email" });
            return PartialView("DataBinding/BindingToEFCore", LargeDatabaseContext.Emails);
        }
        public IActionResult BindingToEFCorePartial() {
            return PartialView("DataBinding/BindingToEFCorePartial", LargeDatabaseContext.Emails);
        }
    }
}
using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.EntityFrameworkCore;

namespace DevExpress.AspNetCore.Demos {
    public class LargeDatabaseContext : DbContext {
        public LargeDatabaseContext(DbContextOptions<LargeDatabaseContext> options)
            : base(options) {
        }
        public DbSet<Email> Emails { get; set; }
    }

    public class Email {
        [Key]
        public int ID { get; set; }
        [Required, MaxLength(100)]
        public string Subject { get; set; }
        [Required, MaxLength(32)]
        public string From { get; set; }
        public DateTime Sent { get; set; }
        public long Size { get; set; }
        public bool HasAttachment { get; set; }
    }
}

Data Annotation

The DevExpress Bootstrap controls rely on the DRY ("Don't Repeat Yourself") ideology of ASP.NET Core MVC validation. This ideology implies that you declaratively specify functionality and behavior of model class properties using Data Annotation attributes. Data validation is performed based on the specified attributes both on the client and server sides.

This demo demonstrates how to change a column's caption and display format using Data Annotation attributes.

Product Price Units In Stock
Chai$18.0039 items
Chang$19.0017 items
Aniseed Syrup$10.0013 items
Chef Anton's Cajun Seasoning$22.0053 items
Chef Anton's Gumbo Mix$21.000 items
Grandma's Boysenberry Spread$25.00120 items
Uncle Bob's Organic Dried Pears$30.0015 items
Northwoods Cranberry Sauce$40.006 items
Mishi Kobe Niku$97.0029 items
Ikura$31.0031 items
@model IEnumerable
@(Html.DevExpress()
    .BootstrapGridView<DevExpress.AspNetCore.DemoModels.DataAnnotationProduct>("dataAnnotationGrid")
    .KeyFieldName(m => m.ProductID)
    .Columns(columns => {
        columns.Add(m => m.ProductName);
        columns.Add(m => m.UnitPrice);
        columns.Add(m => m.UnitsInStock);
    })
    .Routes(routes => routes
        .MapRoute(r => r
            .Action("DataAnnotation")
            .Controller("GridView")))
.Bind(Model))
using DevExpress.AspNetCore.DemoModels;
using Microsoft.AspNetCore.Mvc;
using System;
namespace DevExpress.AspNetCore.Demos {
    public partial class GridViewController : Controller {
        public IActionResult DataAnnotation() {
            return PartialView("DataBinding/DataAnnotation", SimpleBindingContext.GetDataAnnotatedProducts());
        }
    }
}
using System.ComponentModel.DataAnnotations;

namespace DevExpress.AspNetCore.DemoModels {
    public class DataAnnotationProduct {
        [Key]
        public int ProductID { get; set; }

        [Display(Name = "Product")]
        public string ProductName { get; set; }

        [DisplayFormat(DataFormatString = "{0} items")]
        public short? UnitsInStock { get; set; }

        [DisplayFormat(DataFormatString = "c")]
        [Display(Name = "Price")]
        public decimal? UnitPrice { get; set; }
    }
}
Screen Size
Color Themes
Demo QR Code