How to show row-number in first column of WPF Datagrid

22,259

Solution 1

There might be an easier way to do this but I got it to work by using the GetIndex() method on the DataGridRow class. This returns the index in to the data source so might not be exactly what you're after.

enter image description here

the xaml

  <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:sys="clr-namespace:System;assembly=mscorlib"
            xmlns:local="clr-namespace:WpfApplication1"
            Title="MainWindow" Height="350" Width="525">
        <DataGrid>
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Converter={local:RowToIndexConverter}}" />
            </DataGrid.Columns>
            <DataGrid.Items>
                <sys:String>a</sys:String>
                <sys:String>b</sys:String>
                <sys:String>c</sys:String>
                <sys:String>d</sys:String>
                <sys:String>e</sys:String>
            </DataGrid.Items>
        </DataGrid>
    </Window>

and the converter.

public class RowToIndexConverter : MarkupExtension, IValueConverter
{
    static RowToIndexConverter converter;

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        DataGridRow row = value as DataGridRow;
        if (row != null)
            return row.GetIndex();
        else
            return -1;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (converter == null) converter = new RowToIndexConverter();
        return converter;
    }

    public RowToIndexConverter()
    {
    }
}

Solution 2

I used Andys example, but I needed to use it from the code behind, so he is my code just in case anyone is looking to do the same as googling was a bit barren.

The C#

    DataGrid dataGrid = new DataGrid();

    DataGridTextColumn column0 = new DataGridTextColumn();
    column0.Header = "#";

    Binding bindingColumn0 = new Binding();
    bindingColumn0.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(DataGridRow), 1);
    bindingColumn0.Converter = new RowToIndexConvertor();

    column0.Binding = bindingColumn0;

    dataGrid.Columns.Add(column0);

Andy's Converter, just added return row.GetIndex() - 1; to start the count at 1, rather than 0.

public class RowToIndexConvertor : MarkupExtension, IValueConverter
{
    static RowToIndexConvertor convertor;

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        DataGridRow row = value as DataGridRow;

        if (row != null)
        {
            return row.GetIndex() + 1;
        }
        else
        {
            return -1;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (convertor == null)
        {
            convertor = new RowToIndexConvertor();
        }

        return convertor;
    }


    public RowToIndexConvertor()
    {

    }
}

Also don't forget the using's

using System;
using System.Windows.Data;
using System.Windows.Controls;
using System.Windows.Markup;
Share:
22,259
Hardik
Author by

Hardik

Updated on October 21, 2020

Comments

  • Hardik
    Hardik over 3 years

    While searching I found that, row number can be set to RowHeader easily:

    void datagrid_LoadingRow(object sender, DataGridRowEventArgs e) 
    { 
         e.Row.Header = e.Row.GetIndex(); 
    } 
    

    It sets row number in RowHeader. But I want to show Row number to first column

    Can any one help me how can I achieve this? Thanks

  • Hardik
    Hardik over 11 years
    Thanks Andy, It worked. Just a litter edit, row.GetIndex() + 1.
  • Pompair
    Pompair over 10 years
    Nice one, although for me it gives at design time one row too much. I have three items in my itemssource but I get four rows in the grid, last one has index 4 and all columns are empty.
  • Gildor
    Gildor over 10 years
    It does not work when there are many rows and row virtualization is enabled.
  • BCA
    BCA over 10 years
    It almost worked for me: the index values are correct on a fresh DataGrid bound to an ObservableCollection, but if an element is removed, the index values of the elements above the removed item do not get updated (so you end up with "0, 1, 2, 4, ...")
  • alvinchesaro
    alvinchesaro about 5 years
    @Gildor is right, set EnableRowVirtualization="False" on the Datagrid... Checkout stackoverflow.com/a/29852087/8110213
  • JobaDiniz
    JobaDiniz almost 5 years
    how can I make it work without disabling virtualization?
  • Sirop4ik
    Sirop4ik over 4 years
    @alvinchesaro you just saved my day