WPF DataGrid Columns

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

GridTextColumn

Use to display the string data.

GridNumericColumn

Use to display the numeric data.

GridCurrencyColumn

Use to display the currency value.

GridPercentColumn

Use to display the percent value

GridMaskColumn

Use to display the data to be masked.

GridTimeSpanColumn

Use to display the time span value

GridDateTimeColumn

Use to display the date time value

GridComboBoxColumn

Use to display the IEnumerable data using ComboBox.

GridCheckBoxColumn

Use to display the boolean type data

GridImageColumn

Use to display the image in each row.

GridHyperlinkColumn

Use to display the Uri data

GridTemplateColumn

Use to display the custom template-specified content.

GridUnboundColumn

Use to display custom information of each record.

GridMultiColumnDropDownList

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,

  1. Automatically generating columns
  2. 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.

WPF datagrid shows customized header template loaded on the header of OrderID column

Data Annotations with AutoGenerateColumns

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.

OrderID and CustomerID column rearranged in WPF datagrid

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.

Columns formatted with DisplayFormatString in WPF datagrid

Manually defining columns

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 click 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.

Resizing cursor shown in between columns of WPF datagrid

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.

Hidden column resizing cursor shown on hidden column of WPF datagrid

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;         
}

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}" />

WPF datagrid shows the drag window of columns

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 and FooterColumnCount 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}"/>

WPF datagrid shown with frozen columns

Limitations

  1. SfDataGrid has support to freeze the number of columns from the left or right. There is no support to freeze a specific column.

DataGrid stacked headers - Multi row headers

SfDataGrid supports additional unbound header rows known as stacked header rows that span across the DataGrid columns using StackedHeaderRows. You can group one or more columns under each stacked header.

Each StackedHeaderRow contains StackedColumns where each StackedColumn contains a number of child columns. The StackedColumn.ChildColumns property returns the columns grouped under the stacked header row. The StackedColumn.MappingName is a unique name used for mapping a specific child columns grouped under the same stacked header row whereas, the StackedColumn.HeaderText returns the text displayed in the stacked header row.

<syncfusion:SfDataGrid x:Name="dataGrid"         
                       ItemsSource="{Binding Orders}">
    <syncfusion:SfDataGrid.StackedHeaderRows>
        <syncfusion:StackedHeaderRow>
            <syncfusion:StackedHeaderRow.StackedColumns>
                <syncfusion:StackedColumn ChildColumns="OrderID,CustomerID,CustomerName,ShipCity,Country" HeaderText="Sales Details" MappingName="SalesDetails"/>
            </syncfusion:StackedHeaderRow.StackedColumns>
        </syncfusion:StackedHeaderRow>
        <syncfusion:StackedHeaderRow>
            <syncfusion:StackedHeaderRow.StackedColumns>
                <syncfusion:StackedColumn ChildColumns="OrderID" HeaderText="Order Details" MappingName="OrderDetails"/>
                <syncfusion:StackedColumn ChildColumns="CustomerID,CustomerName" HeaderText="Customer Details" MappingName="CustomerDetails"/>
                <syncfusion:StackedColumn ChildColumns="ShipCity,Country" HeaderText="Shipping Details" MappingName="ShippingDetails"/>
            </syncfusion:StackedHeaderRow.StackedColumns>
        </syncfusion:StackedHeaderRow>
    </syncfusion:SfDataGrid.StackedHeaderRows>
</syncfusion:SfDataGrid>
var stackedHeaderRow = new StackedHeaderRow();
stackedHeaderRow.StackedColumns.Add(new StackedColumn() { ChildColumns = "OrderID" + "," + "CustomerID" + "," + "CustomerName" + "," + "ShipCity" + "," + "Country", HeaderText = "Sales Details" , MappingName="SalesDetails" });
dataGrid.StackedHeaderRows.Add(stackedHeaderRow);
            
var stackedHeaderRow1 = new StackedHeaderRow();
stackedHeaderRow1.StackedColumns.Add(new StackedColumn() { ChildColumns = "OrderID", HeaderText = "Order Details" , MappingName="OrderDetails" });            
stackedHeaderRow1.StackedColumns.Add(new StackedColumn() { ChildColumns = "CustomerID" + "," + "CustomerName", HeaderText = "Customer Details" , MappingName="CustomerDetails" });
stackedHeaderRow1.StackedColumns.Add(new StackedColumn() { ChildColumns = "ShipCity" + "," + "Country", HeaderText = "Shipping Details" , MappingName="ShippingDetails" });
dataGrid.StackedHeaderRows.Add(stackedHeaderRow1);

WPF datagrid shown with stacked header rows

You can also add the stacked headers using GroupName property of Data Annotations Display attributes.

public class OrderInfo
{
    private int orderID;
    private string customerId;
    private string country;
    private string customerName;
    private string shippingCity;
        
    public int OrderID
    {
        get { return orderID; }
        set { orderID = value; }
    }

    [Display(GroupName = "Customer Details")]

    public string CustomerID
    {
        get { return customerId; }
        set { customerId = value; }
    }

    [Display(GroupName = "Customer Details")]        

    public string CustomerName
    {
        get { return customerName; }
        set { customerName = value; }
    }

    [Display(GroupName = "Shipping Details")]

    public string Country
    {
        get { return country; }
        set { country = value; }
    }

    [Display(GroupName = "Shipping Details")]

    public string ShipCity
    {
        get { return shippingCity; }
        set { shippingCity = value; }
    }
}

Stacked headers shown with defined GroupName properties in WPF datagrid

Adding ChildColumns

You can add the child columns in particular stacked header directly.

var childColumn = this.dataGrid.StackedHeaderRows[1].StackedColumns[0].ChildColumns;
            this.dataGrid.StackedHeaderRows[1].StackedColumns[0].ChildColumns = childColumn + "," + "OrderDate" + "," + "Discount";

Removing ChildColumns

Similarly, you can remove the child columns from particular stacked header directly.

var removingColumns = this.dataGrid.StackedHeaderRows[0].StackedColumns[0].ChildColumns.Split(',').ToList<string>();   
string childColumns = string.Empty;

foreach(var stackedColumnName in removingColumns.ToList())
{

    if (stackedColumnName.Equals("OrderID"))
    {
        removingColumns.Remove(stackedColumnName);
    }

    else
        childColumns = childColumns + stackedColumnName + ",";
}

this.dataGrid.StackedHeaderRows[0].StackedColumns[0].ChildColumns = childColumns;

Changing stacked header row height

You can change the height of StackedHeaderRows by using VisualContainer.RowHeights property.

using Syncfusion.UI.Xaml.Grid.Helpers;

var visualContainer = dataGrid.GetVisualContainer();            
int count = dataGrid.StackedHeaderRows.Count;

for (int i = 0; i < count; i++)
{               
    visualContainer.RowHeights[i] = 50;
}            
visualContainer.InvalidateMeasure();

You can also change the height of stacked header rows using SfDataGrid.QueryRowHeight event.

using Syncfusion.UI.Xaml.Grid;

this.dataGrid.QueryRowHeight += dataGrid_QueryRowHeight;

void dataGrid_QueryRowHeight(object sender, Syncfusion.UI.Xaml.Grid.QueryRowHeightEventArgs e)
{

    if(e.RowIndex <this.dataGrid.GetHeaderIndex())
    {
        e.Height = 50;
        e.Handled = true;
    }
}

DataGrid - Auto size columns

SfDataGrid allows you to set the column widths based on certain logic using SfDataGrid.ColumnSizer or GridColumn.ColumnSizer property. Below is the list of predefined column sizing options available.

Type Column width
Star Divides the total width equally for columns.
Auto Calculates the width of column based on header and cell contents. So that header and cell content’s are not truncated.
AutoWithLastColumnFill Applies GridLengthUnitType.Auto width to all the columns except last column which is visible and the remaining width from total width of SfDataGird is set to last column.
AutoLastColumnFill Applies GridLengthUnitType.Auto width to all the columns except last column which is visible and sets the maximum between last column auto spacing width and remaining width to last column.
SizeToCells Calculates the width of column based on cell contents. So that cell content’s are not truncated.
SizeToHeader Calculates the width of column based on header content. So that header content is not truncated.
None Default column width or defined width set to column.

NOTE

ColumnSizer will not work when the column width defined explicitly. ColumnSizer calculates column width based on MinWidth and MaxWidth properties.

Below code, applies GridLengthUnitType.Star to equally set width for SfDataGrid.Columns.

<syncfusion:SfDataGrid  x:Name="dataGrid"
                        AutoGenerateColumns="True"
                        ColumnSizer="Star"
                        ItemsSource="{Binding Orders}" />

Columns width initialized with GridLengthUnitType.Star in WPF datagrid.

NOTE

The GridColumn.ColumnSizer takes higher priority than the SfDataGrid.ColumnSizer.

Fill remaining width for any column instead of last column when ColumnSizer is AutoLastColumnFill or AutoWithLastColumnFill 

In SfDataGrid while setting SfDataGrid.ColumnSizer as AutoLastColumnFill or AutoWithLastColumnFill remaining width is applied to last column. You can apply the remaining width to specific column by setting GridColumn.ColumnSizer property as like below.

<Syncfusion:SfDataGrid x:Name="datagrid"                                      
                       ColumnSizer="AutoWithLastColumnFill"
                       ItemsSource="{Binding OrderInfoCollection }">
            <Syncfusion:SfDataGrid.Columns>
                <Syncfusion:GridTextColumn MappingName="OrderID" HeaderText="OrderID" ColumnSizer="AutoLastColumnFill"/>
                <Syncfusion:GridTextColumn MappingName="CustomerID" HeaderText="CustomerID" />
                <Syncfusion:GridTextColumn MappingName="CustomerName" HeaderText="CustomerName"/>
                <Syncfusion:GridTextColumn MappingName="Country" HeaderText="Country"/>
                <Syncfusion:GridTextColumn MappingName="ShipCity" HeaderText="ShipCity"/>
            </Syncfusion:SfDataGrid.Columns>
</Syncfusion:SfDataGrid>
this.datagrid.ColumnSizer = GridLengthUnitType.AutoLastColumnFill;
this.datagrid.Columns["OrderID"].ColumnSizer = GridLengthUnitType.AutoWithLastColumnFill;

WPF datagrid showing OrderID column filled with remaining width instead of last column

Refreshing ColumnSizer at runtime

You can refresh the ColumnSizer at runtime by calling SfDataGrid.GridColumnSizer.Refresh method.
SfDataGrid support to recalculates the column auto width by calling reset methods of GridColumnSizer. GridColumnSizer.ResetAutoCalculationforAllColumns method reset widths to all columns. GridColumnSizer.ResetAutoCalculation method reset the width to particular column.

NOTE

The GridColumnSizer.ResetAutoCalculationforAllColumns or GridColumnSizer.ResetAutoCalculation methods applicable for Auto, AutoWithLastColumnFill, AutoLastColumnFill, SizeToCells types.

For example, you can refresh all the column’s width based on the cell contents of newly added records at runtime.

var viewModel = this.dataGrid.DataContext as ViewModel;
viewModel.Orders.Add(new OrderInfo(11, "BLFKI", "Maria Joseph Anders"));

this.dataGrid.GridColumnSizer.ResetAutoCalculationforAllColumns();
this.dataGrid.GridColumnSizer.Refresh();

Resetting column width to apply ColumnSizer

When the width of the column is explicitly defined or column is resized, then column width is not changed based on GridColumnSizer. You can reset GridColumn.Width by setting double.NaN to apply column width based on column sizer.

foreach (var column in dataGrid.Columns)
{

    if (!double.IsNaN(column.Width))
        column.Width = double.NaN;
}
this.dataGrid.GridColumnSizer.Refresh();

Customizing built-in column sizing logic

SfDataGrid process column sizing operations in GridColumnSizer class. You can customize the column sizing operations by overriding GridColumnSizer and set it to SfDataGrid.GridColumnSizer.

this.dataGrid.GridColumnSizer = new GridColumnSizerExt(dataGrid);

public class GridColumnSizerExt:GridColumnSizer
{

    public GridColumnSizerExt(SfDataGrid dataGrid)
        :base(dataGrid)
    {

    }        

    // Calculate Width for column when ColumnSizer is SizeToCells.        

    protected override double CalculateCellWidth(GridColumn column, bool setWidth = true)
    {
        return base.CalculateCellWidth(column, setWidth);
    }

    //Calculate Width for the column when ColumnSizer is SizeToHeader

    protected override double CalculateHeaderWidth(GridColumn column, bool setWidth = true)
    {
        return base.CalculateHeaderWidth(column, setWidth);
    }
}

Auto width calculation based on font settings

By default, the ColumnSizer calculates column’s width based on fixed FontSize, FontFamily, Margin,SortIconWidth, FilterIconWidth. You can change the calculation by customized settings.

Changing Sort and Filter Icon width

You can change the filter icon and sort icon widths for column width calculation by setting GridColumnSizer.SortIconWidth and GridColumnSizer.FilterIconWidth properties.

dataGrid.GridColumnSizer.SortIconWidth = 20;
dataGrid.GridColumnSizer.FilterIconWidth = 20;

Changing Font settings for SfDataGrid

You can change the font settings for column width calculation by setting GridColumnSizer.FontSize, GridColumnSizer.FontFamily and GridColumnSizer.Margin properties. This settings will be considered for all columns.

this.dataGrid.GridColumnSizer.FontSize = 10.0;
this.dataGrid.GridColumnSizer.FontFamily = new FontFamily("TimesNewRoman");
this.dataGrid.GridColumnSizer.Margin = new Thickness(9, 3, 1, 3);

Changing Font settings for one Column

You can change the font setting for one column width calculation using GridColumnSizer.SetFontFamily, GridColumnSizer.SetFontSize and GridColumnSizer.SetMargin static methods of GridColumnSizer to GridColumn.

var gridColumn = this.dataGrid.Columns[0];
GridColumnSizer.SetFontFamily(gridColumn, new FontFamily("TimesNewRoman"));
GridColumnSizer.SetFontSize(gridColumn, 10.0);
GridColumnSizer.SetMargin(gridColumn, new Thickness(9, 3, 1, 3));

You can also change the font setting for one column width calculation using GetFormattedText method.

this.dataGrid.GridColumnSizer = new ColumnSizerExt(this.dataGrid);

public class ColumnSizerExt : GridColumnSizer
{
    public ColumnSizerExt(SfDataGrid grid) : base(grid)
    {
    }

    protected override FormattedText GetFormattedText(GridColumn column, object record, string displayText)
    {
        var formattedText = base.GetFormattedText(column, record, displayText);

        if (column.MappingName.Equals("OrderID"))
        {            
            formattedText.SetFontFamily(new FontFamily("TimesNewRoman"));
            formattedText.SetFontSize(10);
        }
        return formattedText;
    }
}

Star column sizer ratio support

You can customize the ColumnSizer.Star width calculation logic by overriding SetStarWidth method of GridColumnSizer.

For example, you can calculate the column width, with specified ratios instead of dividing equal width for all columns in Star calculation using ColumnRatio attached property.

public static class StarRatio
{

    public static int GetColumnRatio(DependencyObject obj)
    {
        return (int)obj.GetValue(ColumnRatioProperty);
    }

    public static void SetColumnRatio(DependencyObject obj, int value)
    {
        obj.SetValue(ColumnRatioProperty, value);
    }

    public static readonly DependencyProperty ColumnRatioProperty = DependencyProperty.RegisterAttached("ColumnRatio", typeof(int), typeof(StarRatio), new PropertyMetadata(1, null));
}

Below code to define the star width calculation based on the ColumnRatio.

//Assign the customized GridColumnSizerExt to SfDataGrid.GridColumnSizer
this.dataGrid.GridColumnSizer = new GridColumnSizerExt(dataGrid);

public class GridColumnSizerExt : GridColumnSizer
{

    public GridColumnSizerExt(SfDataGrid grid)
        : base(grid)
    {

    }

    protected override void SetStarWidth(double remainingColumnWidth, IEnumerable<GridColumn> remainingColumns)
    {
        var removedColumn = new List<GridColumn>();
        var columns = remainingColumns.ToList();
        var totalRemainingStarValue = remainingColumnWidth;
        double removedWidth = 0;
        bool isRemoved;

        while (columns.Count > 0)
        {
            isRemoved = false;
            removedWidth = 0;
            var columnsCount = 0;

            columns.ForEach((col) =>
            {
                columnsCount += StarRatio.GetColumnRatio(col);
            });

            double starWidth = Math.Floor((totalRemainingStarValue / columnsCount));
            var column = columns.First();
            starWidth *= StarRatio.GetColumnRatio(column);
            double computedWidth = SetColumnWidth(column, starWidth);

            if (starWidth != computedWidth && starWidth > 0)
            {
                isRemoved = true;
                columns.Remove(column);

                foreach (var remColumn in removedColumn)
                {

                    if (!columns.Contains(remColumn))
                    {
                        removedWidth += remColumn.ActualWidth;
                        columns.Add(remColumn);
                    }
                }
                removedColumn.Clear();
                totalRemainingStarValue += removedWidth;
            }

            totalRemainingStarValue = totalRemainingStarValue - computedWidth;

            if (!isRemoved)
            {
                columns.Remove(column);

                if (!removedColumn.Contains(column))
                    removedColumn.Add(column);
            }
        }
    }
}}

Below code uses the ColumnRatio to apply the defined star width for each column.

<syncfusion:SfDataGrid x:Name="dataGrid"
                       ItemsSource="{Binding Orders}"  
                       ColumnSizer="Star"
                       AutoGenerateColumns="False">
  <syncfusion:SfDataGrid.Columns>;
        <syncfusion:GridTextColumn  HeaderText="Order ID"
                                    MappingName="OrderID"
                                    local:StarRatio.ColumnRatio="1" />
        <syncfusion:GridTextColumn  HeaderText="Customer ID"
                                    MappingName="CustomerID"
                                    local:StarRatio.ColumnRatio="2" />
        <syncfusion:GridTextColumn  HeaderText="Customer Name"
                                    MappingName="CustomerName"
                                    local:StarRatio.ColumnRatio="3" />
   </syncfusion:SfDataGrid.Columns>
</syncfusion:SfDataGrid>

WPF datagrid shows columns width defined based on ColumnRatio

Change the width of GridComboBoxColumn based on it’s ItemsSource

By default, the ColumnSizer calculates auto width based on the column content. You can change the auto width calculation for GridComboBoxColumn based on its items source by overriding the CalculateCellWidth virtual method.

Below code creates CustomColumnSizer to change the width of GridComboboxColumn and set to SfDataGrid.GridColumnSizer.

this.dataGrid.GridColumnSizer = new CustomColumnSizer(this.dataGrid);

public class CustomColumnSizer:GridColumnSizer
{

    public CustomColumnSizer(SfDataGrid grid)
        : base(grid)
    {
    }
       
    protected override double CalculateCellWidth(GridColumn column, bool setWidth = true)
    {            

        if (column is GridComboBoxColumn)
        {                                
            double colWidth = double.MaxValue;                               
            var source = (column as GridComboBoxColumn).ItemsSource;                
            string maximumComboItemsText = string.Empty;                
            var clientSize = new Size(colWidth, DataGrid.RowHeight);                

            foreach (var comboItems in source)
           {
                string comboItemText = (string)comboItems;

                if (maximumComboItemsText.Length < comboItemText.Length)
                    maximumComboItemsText = comboItemText;                   
            }                
            var measureSize= MeasureText(clientSize,maximumComboItemsText,column,null,GridQueryBounds.Width);
            return measureSize.Width + SystemParameters.ScrollWidth;
        }                

        else
            return base.CalculateCellWidth(column, setWidth);
    }      
}

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>

WPF datagrid shows ViewModel.AllowFiltering property binded to GridColumns.AllowFiltering