GridView
in namespace DotVVM.BusinessPack.Controls
A multi-purpose grid control with advanced binding and templating options and sorting support.
Usage & Scenarios
This control is different from the built-in GridView and is not derived from it.
The Business Pack GridView
control is a advanced grid control with many features.
The version 1.1 supports the following features (except of the features supported in the built-in GridView):
- Inline Insert row
- Column Hiding
- Column Reordering
- Column Resizing
- Row Reordering
The following features are planned to be added in the following releases:
- Customizable Filters
- Grouping
- Row Detail
Sample 1: Basic Usage
The DataSource
property expects BusinessPackDataSet
object and defines the data for the control.
The Columns
collection specifies all columns in the control.
The HeaderTemplate
property of the column defines the text displayed in the column header.
Column Types
The <bp:GridViewTextColumn>
renders a text, numeric or date values in the cell. The ValueBinding
expression specifies the property to be rendered.
The FormatString
property specifies the format of the value (for numeric and date columns).
The <bp:GridViewTemplateColumn>
renders a specified template in the grid cell.
<bp:GridView DataSource="{value: Customers}">
<Columns>
<bp:GridViewTextColumn ValueBinding="{value: Id}" HeaderText="ID" />
<bp:GridViewTextColumn ValueBinding="{value: Name}" HeaderText="Name" />
<bp:GridViewTextColumn ValueBinding="{value: BirthDate}" HeaderText="Birth Date"
FormatString="dd.MM.yyyy" />
<bp:GridViewTemplateColumn>
<ContentTemplate>
<b>{{value: Orders}}</b>
</ContentTemplate>
</bp:GridViewTemplateColumn>
</Columns>
</bp:GridView>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DotVVM.Framework.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample1
{
public class ViewModel : DotvvmViewModelBase
{
public BusinessPackDataSet<Customer> Customers { get; set; }
public override Task Init()
{
Customers = new BusinessPackDataSet<Customer>
{
OnLoadingData = GetData,
SortingOptions =
{
SortExpression = nameof(Customer.Id)
}
};
return base.Init();
}
public GridViewDataSetLoadedData<Customer> GetData(IGridViewDataSetLoadOptions gridViewDataSetOptions)
{
var queryable = GetQueryable(15);
return queryable.GetDataFromQueryable(gridViewDataSetOptions);
}
private IQueryable<Customer> GetQueryable(int size)
{
var numbers = new List<Customer>();
for (var i = 0; i < size; i++)
{
numbers.Add(new Customer { Id = i + 1, Name = $"Customer {i + 1}", BirthDate = DateTime.Now.AddYears(-i), Orders = i });
}
return numbers.AsQueryable();
}
}
}
using System;
using System.Linq;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample1
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName => !string.IsNullOrWhiteSpace(Name) ? Name.Split(' ').LastOrDefault() : "";
public DateTime BirthDate { get; set; }
public int Orders { get; set; }
}
}
Sample 2: Grid Headers
When the DataSource
is empty, the grid will not appear at all by default. The ShowHeaderWhenNoData
property can be used to make the grid header visible even if there are no data.
The HeaderCssClass
property of the column sets the CSS class to the column header cell.
To place custom content in the header cell, you can use the HeaderTemplate
property.
<bp:GridView DataSource="{value: Customers}"
ShowHeaderWhenNoData="true">
<Columns>
<bp:GridViewTextColumn ValueBinding="{value: Id}"
HeaderText="Customer ID" />
<bp:GridViewTextColumn ValueBinding="{value: Name}"
HeaderCssClass="gridview-header-highlight">
<HeaderTemplate>
<i>Name</i>
</HeaderTemplate>
</bp:GridViewTextColumn>
</Columns>
</bp:GridView>
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DotVVM.Framework.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample2
{
public class ViewModel : DotvvmViewModelBase
{
public bool ShowHeaderWhenNoData { get; set; }
public BusinessPackDataSet<Customer> Customers { get; set; }
public override Task Init()
{
Customers = new BusinessPackDataSet<Customer>
{
OnLoadingData = GetData,
SortingOptions =
{
SortExpression = nameof(Customer.Id)
}
};
return base.Init();
}
public GridViewDataSetLoadedData<Customer> GetData(IGridViewDataSetLoadOptions gridViewDataSetOptions)
{
var queryable = GetQueryable(15);
return queryable.GetDataFromQueryable(gridViewDataSetOptions);
}
private IQueryable<Customer> GetQueryable(int size)
{
var numbers = new List<Customer>();
for (var i = 0; i < size; i++)
{
numbers.Add(new Customer { Id = i + 1, Name = $"Customer {i + 1}" });
}
return numbers.AsQueryable();
}
}
}
using System;
using System.Linq;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample2
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName => !string.IsNullOrWhiteSpace(Name) ? Name.Split(' ').LastOrDefault() : "";
public DateTime BirthDate { get; set; }
public int Orders { get; set; }
}
}
Sample 3: Grid Footer
The ShowFooter
specifies whether the row footer is displayed or not. By default, it is hidden.
The FooterTemplate
property of the column can be used to customize the content of the column footer cell.
<bp:GridView DataSource="{value: Customers}"
ShowFooter="true">
<Columns>
<bp:GridViewTextColumn ValueBinding="{value: Id}" HeaderText="ID" />
<bp:GridViewTextColumn ValueBinding="{value: Name}" HeaderText="Name" />
<bp:GridViewTextColumn ValueBinding="{value: Orders}" HeaderText="Orders"
FooterCssClass="gridview-footer">
<FooterTemplate>
<p>Total orders: {{value: TotalOrders}}</p>
</FooterTemplate>
</bp:GridViewTextColumn>
</Columns>
</bp:GridView>
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DotVVM.Framework.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample3
{
public class ViewModel : DotvvmViewModelBase
{
public int TotalOrders => Customers.Items.Sum(c => c.Orders);
public BusinessPackDataSet<Customer> Customers { get; set; }
public override Task Init()
{
Customers = new BusinessPackDataSet<Customer>
{
OnLoadingData = GetData,
SortingOptions =
{
SortExpression = nameof(Customer.Id)
}
};
return base.Init();
}
public GridViewDataSetLoadedData<Customer> GetData(IGridViewDataSetLoadOptions gridViewDataSetOptions)
{
var queryable = GetQueryable(15);
return queryable.GetDataFromQueryable(gridViewDataSetOptions);
}
private IQueryable<Customer> GetQueryable(int size)
{
var numbers = new List<Customer>();
for (var i = 0; i < size; i++)
{
numbers.Add(new Customer { Id = i + 1, Name = $"Customer {i + 1}", Orders = i });
}
return numbers.AsQueryable();
}
}
}
using System;
using System.Linq;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample3
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName => !string.IsNullOrWhiteSpace(Name) ? Name.Split(' ').LastOrDefault() : "";
public DateTime BirthDate { get; set; }
public int Orders { get; set; }
}
}
Sample 4: Sorting
By default, the sorting is not enabled on any column. You can use the AllowSorting
property to enable it.
The columns which have the ValueBinding
, will sort using the specified expression by default. If the column doesn't have this property, or you need to use another column for sorting, you can use the SortExpression
property. This property takes precedence over the ValueBinding
.
To customize the icons for sorting, you can use the SortAscendingHeaderCssClass
and SortDescendingHeaderCssClass
properties which specify the CSS class to be added to the header of the column which is used for the searching.
You can also set these properties on the GridView
control instead of declaring them for each column separately, using GridViewColumn.SortAscendingHeaderCssClass="value"
.
<bp:GridView DataSource="{value: Customers}">
<Columns>
<bp:GridViewTextColumn ValueBinding="{value: Id}"
HeaderText="Id"
AllowSorting="true"
SortAscendingHeaderCssClass="sort-asc-custom"
SortDescendingHeaderCssClass="sort-desc-custom" />
<bp:GridViewTextColumn ValueBinding="{value: Name}"
HeaderText="Name"
AllowSorting="true"
SortExpression="LastName" />
<bp:GridViewTextColumn ValueBinding="{value: Orders}"
HeaderText="Orders"
AllowSorting="true" />
</Columns>
</bp:GridView>
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DotVVM.Framework.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample4
{
public class ViewModel : DotvvmViewModelBase
{
public BusinessPackDataSet<Customer> Customers { get; set; }
public override Task Init()
{
Customers = new BusinessPackDataSet<Customer>
{
OnLoadingData = GetData,
SortingOptions =
{
SortExpression = nameof(Customer.Id)
}
};
return base.Init();
}
public GridViewDataSetLoadedData<Customer> GetData(IGridViewDataSetLoadOptions gridViewDataSetOptions)
{
var queryable = GetQueryable(15);
return queryable.GetDataFromQueryable(gridViewDataSetOptions);
}
private IQueryable<Customer> GetQueryable(int size)
{
var numbers = new List<Customer>();
for (var i = 0; i < size; i++)
{
numbers.Add(new Customer { Id = i + 1, Name = $"Customer {i + 1}", Orders = i });
}
return numbers.AsQueryable();
}
}
}
using System;
using System.Linq;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample4
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName => !string.IsNullOrWhiteSpace(Name) ? Name.Split(' ').LastOrDefault() : "";
public DateTime BirthDate { get; set; }
public int Orders { get; set; }
}
}
Sample 5: Paging
The paging relies on the DataPager control and the use of the BusinessPackDataSet
object.
<bp:GridView DataSource="{value: Customers}">
<Columns>
<bp:GridViewTextColumn ValueBinding="{value: Id}" HeaderText="ID" />
<bp:GridViewTextColumn ValueBinding="{value: Name}" HeaderText="Name" />
<bp:GridViewTextColumn ValueBinding="{value: BirthDate}" HeaderText="Birth Date"
FormatString="dd.MM.yyyy" />
<bp:GridViewTextColumn ValueBinding="{value: Orders}" HeaderText="Orders" />
</Columns>
</bp:GridView>
<bp:DataPager DataSet="{value: Customers}" />
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DotVVM.Framework.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample5
{
public class ViewModel : DotvvmViewModelBase
{
public BusinessPackDataSet<Customer> Customers { get; set; }
public override Task Init()
{
Customers = new BusinessPackDataSet<Customer>
{
OnLoadingData = GetData,
PagingOptions =
{
PageSize = 5
},
SortingOptions =
{
SortExpression = nameof(Customer.Id)
}
};
return base.Init();
}
public GridViewDataSetLoadedData<Customer> GetData(IGridViewDataSetLoadOptions gridViewDataSetOptions)
{
var queryable = GetQueryable(15);
return queryable.GetDataFromQueryable(gridViewDataSetOptions);
}
private IQueryable<Customer> GetQueryable(int size)
{
var numbers = new List<Customer>();
for (var i = 0; i < size; i++)
{
numbers.Add(new Customer { Id = i + 1, Name = $"Customer {i + 1}", BirthDate = DateTime.Now.AddYears(-i), Orders = i });
}
return numbers.AsQueryable();
}
}
}
using System;
using System.Linq;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample5
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName => !string.IsNullOrWhiteSpace(Name) ? Name.Split(' ').LastOrDefault() : "";
public DateTime BirthDate { get; set; }
public int Orders { get; set; }
}
}
Sample 6: Inline Editing
The InlineEditing
property can be use to enable the user edit rows directly in the grid.
Every column has the IsEditable
property which specifies whether the column can be edited or not.
The columns also have the EditTemplate
property which can be used to define a custom edit template for the cell.
The object that is currently being edited, is identified by the Customers.RowEditOptions.EditRowId
property which contains the primary key of the edited object. The name of the property which is a primary key, is stored in Customers.RowEditOptions.PrimaryKeyPropertyName
.
<bp:GridView DataSource="{value: Customers}"
InlineEditing="true">
<Columns>
<bp:GridViewTextColumn ValueBinding="{value: Id}"
HeaderText="ID"
IsEditable="false" />
<bp:GridViewTextColumn ValueBinding="{value: Name}"
HeaderText="Name" />
<bp:GridViewTemplateColumn HeaderText="Birthdate">
<ContentTemplate>
<dot:Literal Text="{value: BirthDate}"
FormatString="dd.MM.yyyy" />
</ContentTemplate>
<EditTemplate>
<bp:DateTimePicker SelectedDate="{value: BirthDate}"
FormatString="dd.MM.yyyy"
Mode="Date" />
</EditTemplate>
</bp:GridViewTemplateColumn>
<bp:GridViewTextColumn ValueBinding="{value: Orders}" />
<bp:GridViewTemplateColumn>
<ContentTemplate>
<dot:Button Text="Edit" Click="{command: _parent.EditCustomer(_this)}"/>
</ContentTemplate>
<EditTemplate>
<dot:Button Text="Save" Click="{command: _parent.UpdateCustomer(_this)}"/>
<dot:Button Text="Cancel" Click="{command: _parent.CancelEditCustomer()}"/>
</EditTemplate>
</bp:GridViewTemplateColumn>
</Columns>
</bp:GridView>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DotVVM.BusinessPack.Controls;
using DotVVM.Framework.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample6
{
public class ViewModel : DotvvmViewModelBase
{
public bool IsEditing { get; set; }
public BusinessPackDataSet<Customer> Customers { get; set; }
public override Task Init()
{
Customers = new BusinessPackDataSet<Customer>
{
OnLoadingData = GetData,
RowEditOptions = new RowEditOptions {
PrimaryKeyPropertyName = nameof(Customer.Id),
EditRowId = -1
},
SortingOptions =
{
SortExpression = nameof(Customer.Id)
}
};
return base.Init();
}
public void EditCustomer(Customer customer)
{
Customers.RowEditOptions.EditRowId = customer.Id;
IsEditing = true;
}
public void UpdateCustomer(Customer customer)
{
// Submit customer changes to your database..
CancelEdit();
}
private void CancelEdit()
{
Customers.RowEditOptions.EditRowId = -1;
IsEditing = false;
}
public void CancelEditCustomer()
{
CancelEdit();
Customers.RequestRefresh(true);
}
public GridViewDataSetLoadedData<Customer> GetData(IGridViewDataSetLoadOptions gridViewDataSetOptions)
{
var queryable = GetQueryable(15);
return queryable.GetDataFromQueryable(gridViewDataSetOptions);
}
private IQueryable<Customer> GetQueryable(int size)
{
var numbers = new List<Customer>();
for (var i = 0; i < size; i++)
{
numbers.Add(new Customer { Id = i + 1, Name = $"Customer {i + 1}", BirthDate = DateTime.Now.AddYears(-i), Orders = i });
}
return numbers.AsQueryable();
}
}
}
using System;
using System.Linq;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample6
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName => !string.IsNullOrWhiteSpace(Name) ? Name.Split(' ').LastOrDefault() : "";
public DateTime BirthDate { get; set; }
public int Orders { get; set; }
}
}
Sample 7: Inline Inserting
The InlineInserting
property can enable the inline insert feature on the grid which adds an extra row on the top or the bottom of the table.
The InlineInsertRowPlacement
property specifies whether the insert row is placed on the Top
or the Bottom
of the table.
In the column, you can then specify the InsertTemplate
to provide a custom template for a cell in the insert row.
If you need to combine the inline insert with inline edit, you can provide both templates, or set only the EditTemplate
. Provided that the InsertTemplate
is not set, the EditTemplate
is be used.
<bp:GridView DataSource="{value: Customers}"
InlineInserting="true"
InlineInsertRowPlacement="Bottom">
<Columns>
<bp:GridViewTextColumn ValueBinding="{value: Id}"
HeaderText="ID"
IsEditable="false" />
<bp:GridViewTextColumn ValueBinding="{value: Name}"
HeaderText="Name" />
<bp:GridViewTemplateColumn HeaderText="Birthdate">
<ContentTemplate>
<dot:Literal Text="{value: BirthDate}"
FormatString="dd.MM.yyyy" />
</ContentTemplate>
<InsertTemplate>
<bp:DateTimePicker SelectedDate="{value: BirthDate}"
FormatString="dd.MM.yyyy"
Mode="Date" />
</InsertTemplate>
</bp:GridViewTemplateColumn>
<bp:GridViewTextColumn ValueBinding="{value: Orders}" />
</Columns>
</bp:GridView>
<br />
<bp:Button Text="Add"
Click="{command: InsertNewCustomer()}"
Visible="{value: !IsInserting}" />
<bp:Button Text="Save"
Click="{command: SaveNewCustomer()}"
Visible="{value: IsInserting}" />
<bp:Button Text="Cancel"
Click="{command: CancelInsertNewCustomer()}"
Visible="{value: IsInserting}" />
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DotVVM.BusinessPack.Controls;
using DotVVM.Framework.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample7
{
public class ViewModel : DotvvmViewModelBase
{
public bool IsInserting { get; set; }
public BusinessPackDataSet<Customer> Customers { get; set; }
public override Task Init()
{
Customers = new BusinessPackDataSet<Customer>
{
OnLoadingData = GetData,
RowEditOptions = new RowEditOptions {
PrimaryKeyPropertyName = nameof(Customer.Id)
},
SortingOptions =
{
SortExpression = nameof(Customer.Id)
}
};
return base.Init();
}
public void InsertNewCustomer()
{
Customers.RowInsertOptions.InsertedItem = new Customer {
Id = Customers.Items.Max(c => c.Id) + 1,
Orders = 0
};
IsInserting = true;
}
public void CancelInsertNewCustomer()
{
Customers.RowInsertOptions.InsertedItem = null;
IsInserting = false;
}
public void SaveNewCustomer()
{
// Save inserted item to database
Customers.Items.Add(Customers.RowInsertOptions.InsertedItem);
CancelInsertNewCustomer();
}
public GridViewDataSetLoadedData<Customer> GetData(IGridViewDataSetLoadOptions gridViewDataSetOptions)
{
var queryable = GetQueryable(15);
return queryable.GetDataFromQueryable(gridViewDataSetOptions);
}
private IQueryable<Customer> GetQueryable(int size)
{
var numbers = new List<Customer>();
for (var i = 0; i < size; i++)
{
numbers.Add(new Customer { Id = i + 1, Name = $"Customer {i + 1}", BirthDate = DateTime.Now.AddYears(-i), Orders = i });
}
return numbers.AsQueryable();
}
}
}
using System;
using System.Linq;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample7
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName => !string.IsNullOrWhiteSpace(Name) ? Name.Split(' ').LastOrDefault() : "";
public DateTime BirthDate { get; set; }
public int Orders { get; set; }
}
}
Sample 8: Advanced Column Types
There are several columns which use various Business Pack controls in the insert and edit mode:
the
GridViewComboBoxColumn
renders a ComboBox control.The
GridViewCheckBoxColumn
renders a CheckBox control.
The properties of the column have the same names and meaning like the properties of the control inside the cell.
<bp:GridView DataSource="{value: Orders}"
InlineEditing="true">
<Columns>
<bp:GridViewTextColumn ValueBinding="{value: Id}"
HeaderText="Order ID" />
<bp:GridViewComboBoxColumn ValueBinding="{value: DeliveryType}"
DataSourceBinding="{value: _parent.DeliveryTypes}"
HeaderText="Delivery type" />
<bp:GridViewTemplateColumn HeaderText="Date">
<ContentTemplate>
<dot:Literal Text="{value: CreatedDate}"
FormatString="dd.MM.yyyy hh:mm" />
</ContentTemplate>
<EditTemplate>
<bp:DateTimePicker SelectedDate="{value: CreatedDate}"
FormatString="dd.MM.yyyy hh:mm"
Mode="DateTime" />
</EditTemplate>
</bp:GridViewTemplateColumn>
<bp:GridViewCheckBoxColumn ValueBinding="{value: IsPaid}"
HeaderText="Is Paid?" />
<bp:GridViewTemplateColumn>
<ContentTemplate>
<bp:Button Text="Edit"
Click="{command: _root.Orders.RowEditOptions.EditRowId = Id}" />
</ContentTemplate>
<EditTemplate></EditTemplate>
</bp:GridViewTemplateColumn>
</Columns>
</bp:GridView>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DotVVM.Framework.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample8
{
public class ViewModel : DotvvmViewModelBase
{
public BusinessPackDataSet<Order> Orders { get; set; }
public List<string> DeliveryTypes { get; set; } = new List<string> { "Post office", "Home" };
public override Task Init()
{
Orders = new BusinessPackDataSet<Order> {
OnLoadingData = GetData,
RowEditOptions = new RowEditOptions {
PrimaryKeyPropertyName = nameof(Customer.Id),
EditRowId = -1
},
SortingOptions =
{
SortExpression = nameof(Customer.Id)
}
};
return base.Init();
}
public GridViewDataSetLoadedData<Order> GetData(IGridViewDataSetLoadOptions gridViewDataSetOptions)
{
var queryable = GetQueryable(15);
return queryable.GetDataFromQueryable(gridViewDataSetOptions);
}
private IQueryable<Order> GetQueryable(int size)
{
var numbers = new List<Order>();
for (var i = 0; i < size; i++)
{
numbers.Add(new Order { Id = i + 1, DeliveryType = DeliveryTypes[(i + 1) % 2], IsPaid = (i + 1) % 2 == 0, CreatedDate = DateTime.Now.AddDays(-i) });
}
return numbers.AsQueryable();
}
}
}
using System;
using System.Linq;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample8
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName => !string.IsNullOrWhiteSpace(Name) ? Name.Split(' ').LastOrDefault() : "";
public DateTime BirthDate { get; set; }
public int Orders { get; set; }
}
}
using System;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample8
{
public class Order
{
public int Id { get; set; }
public string DeliveryType { get; set; }
public bool IsPaid { get; set; }
public DateTime CreatedDate { get; set; }
}
}
Sample 9: Row Decorators
The RowDecorators
property can specify decorators that are applied to individual grid rows. The decorator can add properties or event handlers to the <tr>
element rendered by the grid.
For the rows in the edit mode, the EditRowDecorators
are used instead of the default decorator collection.
Similarly, for the rows in the insert mode, the InsertRowDecorators
are used.
<bp:GridView DataSource="{value: Customers}"
InlineEditing="true">
<RowDecorators>
<%-- Set different css class for even and odd rows --%>
<dot:Decorator class="{value: Id % 2 == 0 ? 'even-row' : 'odd-row'}" />
<%-- Set background color warning for customer without any orders --%>
<dot:Decorator style="{value: Orders == 0 ? 'background-color: palevioletred !important;' : ''}" />
</RowDecorators>
<EditRowDecorators>
<%-- Set css class for edit row scenario --%>
<dot:Decorator class="edit-row" />
</EditRowDecorators>
<Columns>
<bp:GridViewTextColumn ValueBinding="{value: Id}"
HeaderText="Customer ID" />
<bp:GridViewTextColumn ValueBinding="{value: Name}"
HeaderText="Name" />
<bp:GridViewTextColumn ValueBinding="{value: Orders}"
HeaderText="# of orders" />
<bp:GridViewTemplateColumn>
<ContentTemplate>
<bp:Button Text="Edit"
Click="{command: _root.Customers.RowEditOptions.EditRowId = Id}" />
</ContentTemplate>
<EditTemplate></EditTemplate>
</bp:GridViewTemplateColumn>
</Columns>
</bp:GridView>
<style type="text/css">
.even-row {
background-color: aquamarine !important;
}
.odd-row {
background-color: azure !important;
}
.edit-row {
background-color: yellow !important;
}
</style>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DotVVM.Framework.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample9
{
public class ViewModel : DotvvmViewModelBase
{
public BusinessPackDataSet<Customer> Customers { get; set; }
public override Task Init()
{
Customers = new BusinessPackDataSet<Customer> {
OnLoadingData = GetData,
RowEditOptions = new RowEditOptions {
PrimaryKeyPropertyName = nameof(Customer.Id),
EditRowId = -1
},
SortingOptions =
{
SortExpression = nameof(Customer.Id)
}
};
return base.Init();
}
public GridViewDataSetLoadedData<Customer> GetData(IGridViewDataSetLoadOptions gridViewDataSetOptions)
{
var queryable = GetQueryable(15);
return queryable.GetDataFromQueryable(gridViewDataSetOptions);
}
private IQueryable<Customer> GetQueryable(int size)
{
var numbers = new List<Customer>();
for (var i = 0; i < size; i++)
{
numbers.Add(new Customer { Id = i + 1, Name = $"Customer {i + 1}", BirthDate = DateTime.Now.AddYears(-i), Orders = i });
}
return numbers.AsQueryable();
}
}
}
using System;
using System.Linq;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample9
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName => !string.IsNullOrWhiteSpace(Name) ? Name.Split(' ').LastOrDefault() : "";
public DateTime BirthDate { get; set; }
public int Orders { get; set; }
}
}
Sample 10: User Settings
The AllowReorderColumns
property can be used to let the user reorder the columns.
The UserSettings
property allows to persist the customizations that the user has made to the grid control. This property expects an object of type GridViewUserSettings
which stores the order, widths and visibility of the individual columns.
This object can be JSON-serialized easily and stored in the database, file system or any other data store. When the user customizes anything in the grid, the changes are stored in this object.
Identification of Grid Columns
Since the developer may change the order of the grid columns, add new columns or remove the existing ones, the GridViewUserSettings
object doesn't work with column indexes, but uses column names. You can mark each column in the markup with an unique name that will be used in the user settings object. If you rename the property in the viewmodel, or move the column to another place in the grid, the user settings object won't break and will be able to identify the column.
You can provide the name using the ColumnName
property. If the name is not specified, the GridView will try to determine the column name from the ValueBinding
property. In case of the GridViewTemplateColumn
which does not have the property, the column index will be used instead.
If you use the
UserSettings
property, make sure that at least all template columns have theColumnName
property set. Otherwise the user settings may break in the future when the columns are changed by the application developer.
<bp:GridView DataSource="{value: Customers}"
UserSettings="{value: UserSettings}"
AllowReorderColumns="true">
<Columns>
<bp:GridViewTextColumn ColumnName="CustomerName"
ValueBinding="{value: Name}"
HeaderText="Name" />
<bp:GridViewTextColumn ColumnName="CustomerOrders"
ValueBinding="{value: Orders}"
HeaderText="Orders" />
<bp:GridViewTextColumn ColumnName="CustomerId"
ValueBinding="{value: Id}"
HeaderText="Customer ID" />
<bp:GridViewTextColumn ColumnName="CustomerBirthdate"
ValueBinding="{value: BirthDate}"
FormatString="dd.MM.yyyy"
HeaderText="Birthdate" />
</Columns>
</bp:GridView>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DotVVM.BusinessPack.Controls;
using DotVVM.Framework.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample10
{
public class ViewModel : DotvvmViewModelBase
{
public GridViewUserSettings UserSettings { get; set; }
public BusinessPackDataSet<Customer> Customers { get; set; }
public override Task Init()
{
Customers = new BusinessPackDataSet<Customer> {
OnLoadingData = GetData,
SortingOptions =
{
SortExpression = nameof(Customer.Id)
}
};
UserSettings = new GridViewUserSettings {
EnableUserSettings = true,
ColumnsSettings = new List<GridViewColumnSetting> {
new GridViewColumnSetting {
ColumnName = "CustomerId",
DisplayOrder = 0,
ColumnWidth = 50
},
new GridViewColumnSetting {
ColumnName = "CustomerName",
DisplayOrder = 1,
ColumnWidth = 400
},
new GridViewColumnSetting {
ColumnName = "CustomerBirthdate",
DisplayOrder = 2
},
new GridViewColumnSetting {
ColumnName = "CustomerOrders",
DisplayOrder = 3
}
}
};
return base.Init();
}
public GridViewDataSetLoadedData<Customer> GetData(IGridViewDataSetLoadOptions gridViewDataSetOptions)
{
var queryable = GetQueryable(15);
return queryable.GetDataFromQueryable(gridViewDataSetOptions);
}
private IQueryable<Customer> GetQueryable(int size)
{
var numbers = new List<Customer>();
for (var i = 0; i < size; i++)
{
numbers.Add(new Customer { Id = i + 1, Name = $"Customer {i + 1}", BirthDate = DateTime.Now.AddYears(-i), Orders = i });
}
return numbers.AsQueryable();
}
}
}
using System;
using System.Linq;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample10
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName => !string.IsNullOrWhiteSpace(Name) ? Name.Split(' ').LastOrDefault() : "";
public DateTime BirthDate { get; set; }
public int Orders { get; set; }
}
}
Sample 11: Server Rendering
The control supports also the server-side rendering. In this mode, many functions cannot work since the control is rendered directly in the HTML output.
The server rendering can be turned on using the RenderSettings.Mode
property.
This helps especially the search engines to index the contents of the page. Additionally, the server rendering might make the grid load faster in the browser if there are hundreds of rows or more.
You can read more in the Server-Side HTML Generation and SEO chapter.
<bp:GridView RenderSettings.Mode="Server"
DataSource="{value: Customers}">
<Columns>
<bp:GridViewTextColumn ValueBinding="{value: Id}"
HeaderText="Customer ID" />
<bp:GridViewTextColumn ValueBinding="{value: Name}"
HeaderText="Name" />
<bp:GridViewTextColumn ValueBinding="{value: BirthDate}"
FormatString="dd.MM.yyyy"
HeaderText="Birthdate"/>
<bp:GridViewTemplateColumn HeaderText="# of orders">
<ContentTemplate>
<b>{{value: Orders}}</b>
</ContentTemplate>
</bp:GridViewTemplateColumn>
</Columns>
</bp:GridView>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DotVVM.Framework.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample11
{
public class ViewModel : DotvvmViewModelBase
{
public BusinessPackDataSet<Customer> Customers { get; set; }
public override Task Init()
{
Customers = new BusinessPackDataSet<Customer> {
OnLoadingData = GetData,
SortingOptions =
{
SortExpression = nameof(Customer.Id)
}
};
return base.Init();
}
public GridViewDataSetLoadedData<Customer> GetData(IGridViewDataSetLoadOptions gridViewDataSetOptions)
{
var queryable = GetQueryable(15);
return queryable.GetDataFromQueryable(gridViewDataSetOptions);
}
private IQueryable<Customer> GetQueryable(int size)
{
var numbers = new List<Customer>();
for (var i = 0; i < size; i++)
{
numbers.Add(new Customer { Id = i + 1, Name = $"Customer {i + 1}", BirthDate = DateTime.Now.AddYears(-i), Orders = i });
}
return numbers.AsQueryable();
}
}
}
using System;
using System.Linq;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.GridView.sample11
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName => !string.IsNullOrWhiteSpace(Name) ? Name.Split(' ').LastOrDefault() : "";
public DateTime BirthDate { get; set; }
public int Orders { get; set; }
}
}
Properties
Name | Type | Description | Notes | Default Value | |
---|---|---|---|---|---|
AllowReorderColumns | Boolean | Gets or sets whether it is allowed to change order of GridView columns. |
attribute
static value
bindable
|
False | |
Attributes | Dictionary<String,Object> |
attribute
static value
|
null | ||
ClientIDMode | ClientIDMode | Gets or sets the client ID generation algorithm. |
attribute
static value
|
Static | |
Columns | List<GridViewColumn> | Gets or sets a collection of columns that will be placed inside the grid. |
inner element
static value
default
|
null | |
DataContext | Object | Gets or sets a data context for the control and its children. All value and command bindings are evaluated in context of this value. |
attribute
static value
bindable
|
null | |
DataSource | Object | Gets or sets the source collection or a GridViewDataSet that contains data in the control. |
attribute
bindable
|
null | |
EditRowDecorators | List<Decorator> | Gets or sets a list of decorators that will be applied on each row which is in edit mode. |
inner element
static value
|
null | |
EmptyDataTemplate | ITemplate | Gets or sets the template which will be displayed when the DataSource is empty. |
inner element
static value
bindable
|
null | |
FilterPlacement | GridViewFilterPlacement | Gets or sets the place where the filters will be created. |
attribute
static value
|
HeaderRow | |
FreezeHeaderRow | Boolean | Gets or sets whether the header row is freezed and is always visible. |
attribute
static value
|
False | |
ID | String | Gets or sets the unique control ID. |
attribute
static value
|
null | |
InlineEditing | Boolean | Gets or sets whether the inline editing is allowed in the Grid. If so, you have to use a GridViewDataSet as the DataSource. |
attribute
static value
|
False | |
InlineInserting | Boolean | Gets or sets whether the insert row should be rendered in the Grid. If so, you have to use a BusinessPackDataSet as the DataSource. |
attribute
static value
|
False | |
InlineInsertRowPlacement | InsertRowPlacement | Gets or sets whether the insert row should be rendered in the Grid. If so, you have to use a BusinessPackDataSet as the DataSource. |
attribute
static value
|
Top | |
InnerText | String | Gets or sets the inner text of the HTML element. |
attribute
static value
bindable
|
null | |
InsertRowDecorators | List<Decorator> | Gets or sets a list of decorators that will be applied on insert row. |
inner element
static value
|
null | |
RowDecorators | List<Decorator> | Gets or sets a list of decorators that will be applied on each row which is not in the edit mode. |
inner element
static value
|
null | |
ShowFooter | Boolean | Gets or sets whether the footer should be displayed or not |
attribute
static value
|
False | |
ShowHeaderWhenNoData | Boolean | Gets or sets whether the header row should be displayed when the grid is empty. |
attribute
static value
|
False | |
SortChanged | Action<String> | Gets or sets the command that will be triggered when the user changed the sort order. |
attribute
bindable
|
null | |
UserSettings | GridViewUserSettings | Gets or sets the user's GridView settings. It can be used to persist column visibility, order, width, etc. |
attribute
bindable
|
null | |
Visible | Boolean | Gets or sets whether the control is visible. |
attribute
bindable
|
True |