Columns in WPF DataGrid (SfDataGrid)
26 Feb 202424 minutes to read
WPF DataGrid (SfDataGrid) allows you to add or remove columns using SfDataGrid.Columns property. You can choose the columns to be added from built-in column types or you can create your own column and add to the SfDataGrid.Columns
.
Below are the built-in column types supported in SfDataGrid. Each column has its own properties to handle different types of data.
Column Type | Description |
---|---|
Use to display the string data. | |
Use to display the numeric data. | |
Use to display the currency value. | |
Use to display the percent value | |
Use to display the data to be masked. | |
Use to display the time span value | |
Use to display the date time value | |
Use to display the IEnumerable data using ComboBox. | |
Use to display the boolean type data | |
Use to display the image in each row. | |
Use to display the Uri data | |
Use to display the custom template-specified content. | |
Use to display custom information of each record. | |
Use to display the IEnumerable data using SfMultiColumnDropdownControl. |
Defining columns
You can let the SfDataGrid to create columns or you can manually define columns to be displayed. Below sections explains both ways,
- Automatically generating columns
- Manually define columns
Automatically generating columns
The automatic column generation based on properties of data object can be enabled or disabled by setting SfDataGrid.AutoGenerateColumns. Default value is true
.
Columns are generated based on type of property. For example, GridNumericColumn is added for int
type property. Below are table shows data type and its column type. For remaining types, GridTextColumn
will be added.
Data Type | Column |
---|---|
string, object, dynamic | GridTextColumn |
int, float, double, decimal and also it’s nullable | GridNumericColumn |
DateTime, DateTimeOffset and also it’s nullable | GridDateTimeColumn |
Uri, Uri? | GridHyperLinkColumn |
bool, bool? | GridCheckBoxColumn |
TimeSpan, TimeSpan? | GridTimeSpanColumn |
NOTE
The order of columns in the collection will determine the order of that they will appear in SfDataGrid.
AutoGenerateColumns with different modes
Column auto generation is controlled using SfDataGrid.AutoGenerateColumnsMode property.
The SfDataGrid.AutoGenerateColumnsMode
includes the following modes.
Mode | Behavior | When ItemsSource changed |
---|---|---|
Reset
|
Generates the columns based on the properties defined in the underlying data object. | Keeps the columns added manually. Clears the columns which are auto generated before and creates new columns based on new ItemsSource. |
RetainOld
|
Generates the columns based on the properties defined in the underlying data object if the columns are not defined explicitly. | The same columns will be maintained when changing ItemsSource also. So filtering, sorting and grouping settings will be maintained. |
ResetAll
|
Generates the columns based on the properties defined in the underlying data object. | Clear all the columns including the columns defined manually and creates new columns based on new ItemsSource. |
None
|
Columns will not be generated. | Keeps old columns in DataGrid.Columns collection. |
Auto generating columns for complex type
Custom type (complex type) properties in data object can be auto-generated by setting AutoGenerateColumnsForCustomType property as true. Default value is false.
Custom type properties will be auto-generated through AutoGenerateColumnsModeForCustomType property.
<syncfusion:SfDataGrid ItemsSource="{Binding Source}" x:Name="dataGrid"
AutoGenerateColumnsForCustomType="True"
AutoGenerateColumnsModeForCustomType="Parent"
AllowEditing="True"
AllowFiltering="True"
AllowSorting="True"
ShowGroupDropArea="True"
ColumnSizer="Star" >
</syncfusion:SfDataGrid>
this.dataGrid.AutoGenerateColumnsForCustomType = true;
this.dataGrid.AutoGenerateColumnsModeForCustomType = AutoGenerateColumnsModeForCustomType.Parent;
The AutoGenerateColumnsModeForCustomType
includes the following modes.
Mode | Behavior |
---|---|
Both
|
Specifies that the columns for both the custom type and its inner properties will be auto generated. |
Child
|
Specifies that the columns for all inner properties of custom type column will be auto generated. |
Parent
|
Specifies that the column for only the custom type will be auto generated. |
You can download the sample demo here .
Customize auto-generated columns in DataGrid
You can customize or cancel the generated column by handling AutoGeneratingColumn event. AutoGeneratingColumn
event occurs when the individual column is auto-generated for public and non-static property of underlying data object.
this.dataGrid.AutoGeneratingColumn += dataGrid_AutoGeneratingColumn;
void dataGrid_AutoGeneratingColumn(object sender, AutoGeneratingColumnArgs e)
{
}
AutoGeneratingColumnArgs provides the information about the auto-generated column to the AutoGeneratingColumn
event. AutoGeneratingColumnArgs.Column property returns the newly created column.
Cancel column generation for particular property
You can cancel the specific column adding to the DataGrid by handling AutoGeneratingColumn
event.
In the below code, column generation for OrderID
property is canceled by setting Cancel
property to true
.
this.dataGrid.AutoGeneratingColumn += dataGrid_AutoGeneratingColumn;
void dataGrid_AutoGeneratingColumn(object sender, AutoGeneratingColumnArgs e)
{
if (e.Column.MappingName == "OrderID")
e.Cancel = true;
}
Changing column type
You can change the type of column adding to SfDataGrid by setting the instance of column you want to add in AutoGeneratingColumn
event.
In the below code, column type for UnitPrice
property is changed to GridTextColumn
by setting instance of GridTextColumn to Column
property.
this.dataGrid.AutoGeneratingColumn += dataGrid_AutoGeneratingColumn;
void dataGrid_AutoGeneratingColumn(object sender, AutoGeneratingColumnArgs e)
{
if (e.Column.MappingName == "UnitPrice")
{
if (e.Column is GridNumericColumn)
{
e.Column = new GridTextColumn() { MappingName = "UnitPrice", HeaderText = "Unit Price" };
}
}
}
Changing property settings
You can change the column properties in AutoGeneratingColumn
event handler.
this.dataGrid.AutoGeneratingColumn += dataGrid_AutoGeneratingColumn;
void dataGrid_AutoGeneratingColumn(object sender, AutoGeneratingColumnArgs e)
{
if(e.Column.MappingName=="OrderID")
{
e.Column.AllowEditing = false;
e.Column.AllowSorting = true;
e.Column.AllowFiltering = true;
e.Column.AllowGrouping = false;
e.Column.AllowFocus = true;
e.Column.AllowResizing = false;
e.Column.ColumnSizer = GridLengthUnitType.Auto;
e.Column.AllowDragging = true;
}
}
Setting template to auto-generated column
You can set GridColumn.HeaderTemplate and GridColumn.CellTemplate properties for auto-generated column in AutoGeneratingColumn
event handler.
<Window.Resources>
<DataTemplate x:Key="headerTemplate">
<TextBlock Text="The product has been purchased by the following OrderID" TextWrapping="Wrap" />
</DataTemplate>
</Window.Resources>
this.dataGrid.AutoGeneratingColumn += dataGrid_AutoGeneratingColumn;
void dataGrid_AutoGeneratingColumn(object sender, AutoGeneratingColumnArgs e)
{
if (e.Column.MappingName == "OrderID")
{
e.Column.HeaderTemplate = this.FindResource("headerTemplate") as DataTemplate;
}
}
Below screenshot shows the customized header template loaded on the header of OrderID column.
Data Annotations with AutoGenerateColumns
WPF DataGrid (SfDataGrid) support to generate the columns based on built-in Data Annotation Attributes. Data Annotations ignored, when the AutoGenerateColumns
is set to False.
Exclude column
You can skip the column generation using AutoGenerateField
property or set the Bindable
attribute to false.
[Display(AutoGenerateField = false, Description = "OrderID field is not generated in UI")]
public int OrderID
{
get { return orderID; }
set { orderID = value; }
}
Filtering
You can enable filtering automatically for the field using Display.AutoGenerateFilter
property
[Display(AutoGenerateFilter = true, Description = "Filter enabled for CustomerID column")]
public string CustomerID
{
get { return customerId; }
set { customerId = value; }
}
Editing
You can change the value of the property using Editable
attribute.
[Editable(true)]
public string Country
{
get { return country; }
set { country = value; }
}
Change the HeaderText of column
You can customize header text of column using Display.Name
property.
[Display(Name="Name of the Customer",Description="CustomerName is necessary for identification ")]
public string CustomerName
{
get { return customerName; }
set { customerName = value; }
}
Change the order of the columns
You can change the columns order using DisplayAttribute.Order
property.
[Display(Order=0)]
public int OrderID
{
get { return orderID; }
set { orderID = value; }
}
[Display(Order=-1)]
public string CustomerID
{
get { return customerId; }
set { customerId = value; }
}
The OrderID and CustomerID column rearranged based on specified order.
DataGrid column formatting
You can customize the data format using DataTypeAttribute.DataType
property.
[DataType(DataType.Currency)]
public double UnitPrice
{
get { return unitPrice; }
set { unitPrice = value; }
}
DataGrid read-only column
You can disable the editing for a column using ReadOnly
attribute.
[ReadOnly(true)]
public string Country
{
get { return country; }
set { country = value; }
}
Format datagrid columns using DisplayFormat attribute
The auto-generated columns will be formatted using the DataFormatString property in the DisplayFormat attribute when the DisplayFormat
attribute is defined for the properties defined in the view model. If the DisplayFormat
attribute is defined with the DataFormatString
property, the DataGrid formats the column only based on DataFormatString
, without considering other formatting property settings of columns.
[DisplayFormat(DataFormatString = "Country is {0}")]
public string Country
{
get { return country; }
set { country = value; }
}
[DisplayFormat(DataFormatString = "yyyy")]
public DateTime OrderDate
{
get { return _orderDate; }
set { orderDate = value; }
}
NOTE
The
DataFormatString
attribute will be considered only when the column is auto-generated.
Manually defining columns
WPF DataGrid (SfDataGrid) control allows you to define the columns manually by adding desired column to the SfDataGrid.Columns collection.
<syncfusion:SfDataGrid x:Name="dataGrid"
AutoGenerateColumns="False"
ItemsSource="{Binding Orders}">
<syncfusion:SfDataGrid.Columns>
<syncfusion:GridTextColumn HeaderText="Order ID" MappingName="OrderID" />
<syncfusion:GridTextColumn HeaderText="Customer ID" MappingName="CustomerID" />
<syncfusion:GridTextColumn HeaderText="Customer Name" MappingName="CustomerName" />
<syncfusion:GridTextColumn HeaderText="Country" MappingName="Country" />
<syncfusion:GridNumericColumn HeaderText="Unit Price" MappingName="UnitPrice" />
</syncfusion:SfDataGrid.Columns>
</syncfusion:SfDataGrid>
this.dataGrid.Columns.Add(new GridTextColumn() { HeaderText = "Order ID", MappingName = "OrderID" });
this.dataGrid.Columns.Add(new GridTextColumn() { HeaderText = "Customer ID", MappingName = "CustomerID" });
this.dataGrid.Columns.Add(new GridTextColumn() { HeaderText = "Customer Name", MappingName = "CustomerName" });
this.dataGrid.Columns.Add(new GridTextColumn() { HeaderText = "Country", MappingName = "Country" });
this.dataGrid.Columns.Add(new GridNumericColumn() { HeaderText = "Unit Price", MappingName = "UnitPrice" });
You can refer more information about handling the column level operations for manually defined columns in Column types section.
Column manipulation
You can get the columns (added or auto-generated) from SfDataGrid.Columns property.
Adding column to DataGrid
You can add column at runtime by adding instance of column to SfDataGrid.Columns
property.
this.dataGrid.Columns.Add(new GridTextColumn() { HeaderText = "Order ID", MappingName = "OrderID" });
Accessing column
You can access the column through its column index or GridColumn.MappingName
from the SfDataGrid.Columns collection.
GridColumn column = this.dataGrid.Columns[1];
//OR
GridColumn column = this.dataGrid.Columns["OrderID"];
Clearing or removing column in DataGrid
You can remove all the columns by clearing the SfDataGrid.Columns
property.
this.dataGrid.Columns.Clear();
You can remove a column using Remove and RemoveAt methods.
dataGrid.Columns.Remove(column);
//OR
dataGrid.Columns.RemoveAt(1);
You can also remove the column under one stacked column from StackedHeaderRow.
var childColumns = this.dataGrid.StackedHeaderRows[1].StackedColumns[0].ChildColumns.Split(',');
foreach (var name in childColumns)
{
var column = dataGrid.Columns[name];
if (column == null)
continue;
dataGrid.Columns.Remove(column);
}
DataGrid column resizing
SfDataGrid allows to resize the columns like in excel by resizing column header. This can be enabled or disabled by setting SfDataGrid.AllowResizingColumns or GridColumn.AllowResizing property.
NOTE
Resizing considers MinWidth and MaxWidth of column.
<syncfusion:SfDataGrid x:Name="dataGrid"
AllowResizingColumns="True"
AutoGenerateColumns="True"
ItemsSource="{Binding Orders}" />
You can change the column width by clicking and dragging the resizing cursor at the edge of column header. The resizing cursor appears when you hover the grid line exists between two columns.
Hidden column resizing
SfDataGrid shows indication for hidden columns in column header and also allows end-users to resize the hidden columns when setting SfDataGrid.AllowResizingHiddenColumns property to true
.
Disable resizing
You can cancel resizing of particular column by setting GridColumn.AllowResizing property to false
. In another way, you can cancel the resizing by handling SfDataGrid.ResizingColumns event. The ResizingColumns
event occurs when you start dragging by resizing cursor on headers.
ResizingColumnsEventArgs of ResizingColumns
provides information about the columns’s index and width.
this.dataGrid.ResizingColumns += dataGrid_ResizingColumns;
void dataGrid_ResizingColumns(object sender, ResizingColumnsEventArgs e)
{
if(e.ColumnIndex == 1)
e.Cancel = true;
}
Identify resizing of the column gets completed
SfDataGrid allows you to identify the progress of the resizing of columns through ResizingColumnsEventArgs.Reason property. You can get the width of the column after resizing completed by getting ResizingColumnsEventArgs.Width when ResizingColumnsEventArgs.Reason
is ColumnResizingReason.Resized in ResizingColumns event.
this.dataGrid.ResizingColumns += OnResizingColumns;
void OnResizingColumns(object sender, ResizingColumnsEventArgs e)
{
if (e.Reason == Syncfusion.UI.Xaml.Grid.ColumnResizingReason.Resized)
{
var resizedWidth = e.Width;
}
}
DataGrid column drag and drop
You can allow end-users to rearrange the columns by drag and drop the column headers by setting SfDataGrid.AllowDraggingColumns to true
.
<syncfusion:SfDataGrid x:Name="dataGrid"
AllowDraggingColumns="True"
AutoGenerateColumns="True"
ItemsSource="{Binding Orders}" />
You can enable or disable dragging on particular column using GridColumn.AllowDragging property.
<syncfusion:GridTextColumn AllowDragging="False"
HeaderText="Order ID"
MappingName="OrderID" />
Disable column reordering
You can cancel the particular column dragging by handling SfDataGrid.QueryColumnDragging. QueryColumnDragging
event occurs when you start dragging the column header. QueryColumnDraggingEventArgs of QueryColumnDragging
event provides information about the column triggered this event.
QueryColumnDraggingEventArgs.From
property returns the index of column triggered this event. QueryColumnDraggingEventArgs.To
property returns the index where you try to drop the column. QueryColumnDraggingEventArgs.Reason
returns column dragging details by QueryColumnDraggingReason.
this.dataGrid.QueryColumnDragging += dataGrid_QueryColumnDragging;
void dataGrid_QueryColumnDragging(object sender, QueryColumnDraggingEventArgs e)
{
var column = dataGrid.Columns[e.From];
if (column.MappingName == "CustomerName" && e.Reason == QueryColumnDraggingReason.Dropping)
{
e.Cancel = true;
}
}
Column drag and drop customization
The drag-and-drop operations can be changed by overriding the virtual methods of GridColumnDragDropController class and assigning it to SfDataGrid.GridColumnDragDropController
.
this.dataGrid.GridColumnDragDropController = new CustomDragDropController(dataGrid);
public class CustomDragDropController:GridColumnDragDropController
{
public CustomDragDropController(SfDataGrid dataGrid): base(dataGrid)
{
}
//Returns whether the popup showed its header or not.
public override bool CanShowPopup(GridColumn column)
{
return base.CanShowPopup(column);
}
//Get the corresponding GridRegion at a given point.
public override GridRegion PointToGridRegion(System.Windows.Point point)
{
return base.PointToGridRegion(point);
}
//Occurs when the GridColumn.Hidden property value changed.
protected override void OnColumnHiddenChanged(GridColumn column)
{
base.OnColumnHiddenChanged(column);
}
//Occurs when the popup content is created.
protected override System.Windows.UIElement CreatePopupContent(GridColumn column)
{
return base.CreatePopupContent(column);
}
//Occurs when the popup content is dropped on DataGrid.
protected override void PopupContentDroppedOnGrid(System.Windows.Point point)
{
base.PopupContentDroppedOnGrid(point);
}
//Occurs when the popup content is dropped on header row.
protected override void PopupContentDroppedOnHeaderRow(int oldIndex, int newColumnIndex)
{
base.PopupContentDroppedOnHeaderRow(oldIndex, newColumnIndex);
}
//Occurs when the popup content is dropped.
protected override void OnPopupContentDropped(System.Windows.Point point, System.Windows.Point pointOverGrid)
{
base.OnPopupContentDropped(point, pointOverGrid);
}
//Occurs when the popup content is dropped on GroupDropArea
protected override void PopupContentDroppedOnGroupDropArea(GridColumn column)
{
base.PopupContentDroppedOnGroupDropArea(column);
}
//Occurs when the popup content position changed.
protected override void OnPopupContentPositionChanged(double HorizontalDelta, double VerticalDelta, System.Windows.Point mousePoint, System.Windows.Point mousePointOverGrid)
{
base.OnPopupContentPositionChanged(HorizontalDelta, VerticalDelta, mousePoint, mousePointOverGrid);
}
}
Disabling drag & drop between frozen and non-frozen columns
By default, the columns re-ordering performed between any column regions of columns. You can cancel the dropping action between the frozen and non-frozen columns by handling SfDataGrid.QueryColumnDragging event.
this.dataGrid.QueryColumnDragging += dataGrid_QueryColumnDragging;
void dataGrid_QueryColumnDragging(object sender, QueryColumnDraggingEventArgs e)
{
if (e.Reason == QueryColumnDraggingReason.Dropping)
{
var frozenColIndex = this.dataGrid.FrozenColumnCount + this.dataGrid.ResolveToStartColumnIndex();
if (e.From < frozenColIndex && e.To > frozenColIndex - 1)
e.Cancel = true;
if (e.From > frozenColIndex && e.To < frozenColIndex ||(e.From == frozenColIndex && e.To < frozenColIndex))
e.Cancel = true;
}
}
NOTE
FrozenColumnCount
andFooterColumnCount
should be lesser than the number of Columns that can be displayed in View.
DataGrid freeze columns
You can freeze the columns in view at the left and right side like in excel by setting SfDataGrid.FrozenColumnCount and SfDataGrid.FooterColumnCount properties.
<syncfusion:SfDataGrid x:Name="dataGrid"
AutoGenerateColumns="False"
FrozenColumnCount="2"
ItemsSource="{Binding Orders}"/>
Limitations
- SfDataGrid has support to freeze the number of columns from the left or right. There is no support to freeze a specific column.
Binding column properties with ViewModel
SfDataGrid provides MVVM support for binding GridColumn
properties with ViewModel properties
.
public class ViewModel
{
private bool _allowFiltering =true;
public bool AllowFiltering
{
get { return _allowFiltering; }
set { _allowFiltering = value; }
}
}
Below code, binds the ViewModel.AllowFiltering
property to GridColumn.AllowFiltering
property.
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<syncfusion:SfDataGrid x:Name="dataGrid"
ItemsSource="{Binding Orders}"
AutoGenerateColumns="False">
<syncfusion:SfDataGrid.Columns>
<syncfusion:GridTextColumn MappingName="OrderID" AllowFiltering="{Binding AllowFiltering}"/>
</syncfusion:SfDataGrid.Columns>
</syncfusion:SfDataGrid>