10

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

ASh
  • 34,632
  • 9
  • 60
  • 82
Hardik
  • 1,716
  • 6
  • 27
  • 41
  • I tried using, void datagrid_LoadingRow(object sender, DataGridRowEventArgs e) { e.Row.Header = e.Row.GetIndex(); } It sets Row number in RowHeader, I need to set in Column. – Hardik Feb 25 '13 at 06:34

2 Answers2

19

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()
    {
    }
}
Andy
  • 6,366
  • 1
  • 32
  • 37
  • 3
    Thanks Andy, It worked. Just a litter edit, row.GetIndex() + 1. – Hardik Feb 25 '13 at 07:13
  • 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. – Pompair Oct 23 '13 at 12:33
  • 6
    It does not work when there are many rows and row virtualization is enabled. – Gildor Dec 20 '13 at 15:30
  • 3
    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, ...") – BCA Dec 24 '13 at 15:32
  • 1
    @Gildor is right, set EnableRowVirtualization="False" on the Datagrid... Checkout https://stackoverflow.com/a/29852087/8110213 – alvinchesaro Apr 10 '19 at 15:21
  • how can I make it work without disabling virtualization? – JobaDiniz Aug 01 '19 at 13:11
  • @alvinchesaro you just saved my day – Sirop4ik Jan 27 '20 at 15:59
4

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;
metoyou
  • 639
  • 1
  • 7
  • 22