简体   繁体   English

在 WPF DataGrid 上显示行号的简单方法

[英]Simple way to display row numbers on WPF DataGrid

I just want to display row numbers in the left-most column of my DataGrid .我只想在我的DataGrid最左边的列中显示行号。 Is there some attribute to do this?是否有一些属性可以做到这一点?

Keep in mind, this isn't a primary key for my table.请记住,这不是我的表的主键。 I don't want these row numbers to move with their rows when a column is sorted.当对列进行排序时,我不希望这些行号随行一起移动。 I basically want a running count.我基本上想要一个运行计数。 It doesn't even need to have a header.它甚至不需要标题。

One way is to add them in the LoadingRow event for the DataGrid一种方法是将它们添加到 DataGrid 的 LoadingRow 事件中

<DataGrid Name="DataGrid" LoadingRow="DataGrid_LoadingRow" ...

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

When items are added or removed from the source list then the numbers can get out of sync for a while.在源列表中添加或删除项目时,数字可能会暂时不同步。 For a fix to this, see the attached behavior here:要解决此问题,请参阅此处的附加行为:
WPF 4 DataGrid: Getting the Row Number into the RowHeader WPF 4 DataGrid:将行号放入 RowHeader

Useable like this可以这样使用

<DataGrid ItemsSource="{Binding ...}"
          behaviors:DataGridBehavior.DisplayRowNumber="True"> 

Adding a short info about Fredrik Hedblad answer.添加有关 Fredrik Hedblad 答案的简短信息。

<DataGrid Name="DataGrid" LoadingRow="DataGrid_LoadingRow" ...

void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
    e.Row.Header = (e.Row.GetIndex()+1).ToString(); 
}

...If you want to start numbering from 1 ...如果你想从 1 开始编号

If your data grid has its ItemsSource bound to a collection, bind the AlternationCount property of your data grid to either the the count property of your collection, or to the Items.Count property of your DataGrid as follows:如果数据网格的 ItemsSource 绑定到集合,请将数据网格的 AlternationCount 属性绑定到集合的 count 属性,或绑定到 DataGrid 的 Items.Count 属性,如下所示:

<DataGrid ItemsSource="{Binding MyObservableCollection}" AlternationCount="{Binding MyObservableCollection.Count}" />

Or:或者:

<DataGrid ItemsSource="{Binding MyObservableCollection}" AlternationCount="{Binding Items.Count, RelativeSource={RelativeSource Self}" />

Either should work.要么应该工作。

Then, assuming you're using a DataGridTextColumn for your leftmost column you do the following in your DataGrid.Columns definition:然后,假设您使用 DataGridTextColumn 作为最左边的列,您在 DataGrid.Columns 定义中执行以下操作:

<DataGrid.Columns>
   <DataGridTextColumn Binding="{Binding AlternationIndex, RelativeSource={RelativeSource AncestorType=DataGridRow}}"
</DataGrid.Columns>

If you don't want to start at 0, you can add a converter to your binding to increment the index.如果不想从 0 开始,则可以向绑定添加转换器以增加索引。

It's an old question, but I would like to share something.这是一个老问题,但我想分享一些东西。 I had a similar problem, all I needed was a simple RowHeader numeration of rows and Fredrik Hedblad's answer was almost complete for my problem.我有一个类似的问题,我所需要的只是一个简单的RowHeader行数,而 Fredrik Hedblad 的回答对我的问题来说几乎是完整的。

While this is great:虽然这很棒:

<DataGrid Name="DataGrid" LoadingRow="DataGrid_LoadingRow" ...

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

my headers messed up when removing and adding items.删除和添加项目时,我的标题搞砸了。 If you have buttons responsible for that just add dataGrid.Items.Refresh();如果你有按钮负责,只需添加dataGrid.Items.Refresh(); under the 'deleting' code as in my case:在我的情况下的“删除”代码下:

private void removeButton_Click(object sender, RoutedEventArgs e)
{
    // delete items

    dataGrid.Items.Refresh();
}

That solved desyncronized numeration for me, because refreshing items calls DataGrig_LoadingRow again.这为我解决了不同步的计数,因为刷新项目再次调用DataGrig_LoadingRow

And just to add to the discussion on this... (I spent too much time finding this out!).只是为了增加对此的讨论......(我花了太多时间来发现这一点!)。

You'll need to set the EnableRowVirtualization to False on the datagrid to prevent errors in the row sequencing:您需要在数据网格上将 EnableRowVirtualization 设置为 False 以防止行排序中的错误:

EnableRowVirtualization="False"

The EnableRowVirtualization property is set to true by default. EnableRowVirtualization属性默认设置为true When the EnableRowVirtualization property is set to true, the DataGrid does not instantiate a DataGridRow object for each data item in the bound data source.EnableRowVirtualization属性设置为 true 时,DataGrid 不会为绑定数据源中的每个数据项实例化DataGridRow对象。 Instead, the DataGrid creates DataGridRow objects only when they are needed, and reuses them as much as it can.相反,DataGrid 仅在需要时才创建 DataGridRow 对象,并尽可能多地重用它们。 MSDN Reference here MSDN参考这里

Just another answer to provide almost copy&paste example (not to be encouraged) for new people or people in a rush, inspired by answers inside this post by @GrantA and @Johan Larsson ( + many other people who answered to the numerous posts on that subject)只是另一个为新人或匆忙的人提供几乎复制和粘贴示例(不鼓励)的答案,灵感来自@GrantA 和@Johan Larsson(+许多其他人回答了有关该主题的众多帖子) )

  • You may not want to add the enumeration inside a column您可能不想在列中添加枚举
  • You do not need to re-create your own Attached Property您不需要重新创建自己的附加属性

    <UserControl... <Grid> <DataGrid ItemsSource="{Binding MainData.ProjColl}" AutoGenerateColumns="False" AlternationCount="{ Binding MainData.ProjColl.Count}" > <DataGrid.Columns> <!--Columns given here for example--> ... <DataGridTextColumn Header="Project Name" Binding="{Binding CMProjectItemDirName}" IsReadOnly="True"/> ... <DataGridTextColumn Header="Sources Dir" Binding="{Binding CMSourceDir.DirStr}"/> ... </DataGrid.Columns> <!--The problem of the day--> <DataGrid.RowHeaderStyle> <Style TargetType="{x:Type DataGridRowHeader}"> <Setter Property="Content" Value="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource AncestorType=DataGridRow}}"/> </Style> </DataGrid.RowHeaderStyle> </DataGrid> </Grid> </UserControl>

Note the parenthesis () around (ItemsControl.AlternationIndex) as warned in Fredrik Hedblad answer in Check if Row as odd number请注意 (ItemsControl.AlternationIndex) 周围的括号 (),如Fredrik Hedblad 回答中所警告的那样检查是否行为奇数

在此处输入图片说明

After some Tests with RowHeaderStyle , the repaired and extended sample from NGI:在使用RowHeaderStyle进行一些测试后,来自 NGI 的修复和扩展示例:

        <DataGrid EnableRowVirtualization="false" ItemsSource="{Binding ResultView}" AlternationCount="{Binding ResultView.Count}" RowHeaderWidth="10">
            <DataGrid.RowHeaderStyle>
                <Style TargetType="{x:Type DataGridRowHeader}">
                    <Setter Property="Content" Value="{Binding Path=AlternationIndex, RelativeSource={RelativeSource AncestorType=DataGridRow}}" />
                </Style>
            </DataGrid.RowHeaderStyle>
        </DataGrid>

Using attached properties, full source here .使用附加属性,完整来源在这里

using System.Windows;
using System.Windows.Controls;

public static class Index
{
    private static readonly DependencyPropertyKey OfPropertyKey = DependencyProperty.RegisterAttachedReadOnly(
        "Of",
        typeof(int),
        typeof(Index),
        new PropertyMetadata(-1));

    public static readonly DependencyProperty OfProperty = OfPropertyKey.DependencyProperty;

    public static readonly DependencyProperty InProperty = DependencyProperty.RegisterAttached(
        "In",
        typeof(DataGrid),
        typeof(Index),
        new PropertyMetadata(default(DataGrid), OnInChanged));

    public static void SetOf(this DataGridRow element, int value)
    {
        element.SetValue(OfPropertyKey, value);
    }

    public static int GetOf(this DataGridRow element)
    {
        return (int)element.GetValue(OfProperty);
    }

    public static void SetIn(this DataGridRow element, DataGrid value)
    {
        element.SetValue(InProperty, value);
    }

    public static DataGrid GetIn(this DataGridRow element)
    {
        return (DataGrid)element.GetValue(InProperty);
    }

    private static void OnInChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var row = (DataGridRow)d;
        row.SetOf(row.GetIndex());
    }
}

Xaml: Xml:

<DataGrid ItemsSource="{Binding Data}">
    <DataGrid.RowStyle>
        <Style TargetType="{x:Type DataGridRow}">
            <Setter Property="dataGrid2D:Index.In" 
                    Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
        </Style>
    </DataGrid.RowStyle>

    <DataGrid.RowHeaderStyle>
        <Style TargetType="{x:Type DataGridRowHeader}">
            <Setter Property="Content" 
                    Value="{Binding Path=(dataGrid2D:Index.Of), 
                                    RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" />
        </Style>
    </DataGrid.RowHeaderStyle>
</DataGrid>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM