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

发布于 2024-10-11 23:13:30 字数 144 浏览 8 评论 0原文

我只想在 DataGrid 的最左列中显示行号。是否有某些属性可以执行此操作?

请记住,这不是我的表的主键。当对列进行排序时,我不希望这些行号随行移动。我基本上想要一个运行计数。它甚至不需要有标题。

I just want to display row numbers in the left-most column of my 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

白龙吟 2024-10-18 23:13:30

一种方法是将它们添加到 DataGrid 的 LoadingRow 事件中。

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

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

当从源列表中添加或删除项目时,数字可能会暂时不同步。要解决此问题,请参阅此处附加的行为:
WPF 4 DataGrid:获取行号进入 RowHeader

可以像这样使用

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

One way is to add them in the LoadingRow event for the DataGrid

<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

Useable like this

<DataGrid ItemsSource="{Binding ...}"
          behaviors:DataGridBehavior.DisplayRowNumber="True"> 
ゝ杯具 2024-10-18 23:13:30

添加有关 Fredrik Hedblad 答案的简短信息。

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

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

...如果你想从1开始编号

Adding a short info about Fredrik Hedblad answer.

<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

梦里南柯 2024-10-18 23:13:30

如果数据网格的 ItemsSource 绑定到集合,请将数据网格的 AlternationCount 属性绑定到集合的 count 属性,或者绑定到 DataGrid 的 Items.Count 属性,如下所示:

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

或者:

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

两者都可以。

然后,假设您对最左边的列使用 DataGridTextColumn,则在 DataGrid.Columns 定义中执行以下操作:

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

如果您不想从 0 开始,则可以向绑定添加转换器以增加索引。

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:

<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:

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

〆凄凉。 2024-10-18 23:13:30

这是一个老问题,但我想分享一些东西。我遇到了类似的问题,我所需要的只是一个简单的 RowHeader 行计数,Fredrik Hedblad 的答案几乎可以解决我的问题。

虽然这很棒:

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

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

删除和添加项目时我的标题弄乱了。如果您有负责此操作的按钮,只需在“删除”代码下添加 dataGrid.Items.Refresh(); ,就像我的情况一样:

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

    dataGrid.Items.Refresh();
}

这为我解决了不同步的计数问题,因为刷新项目会调用 DataGrig_LoadingRow再次。

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.

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(); 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.

開玄 2024-10-18 23:13:30

只是为了添加对此的讨论......(我花了太多时间来发现这一点!)。

您需要在数据网格上将 EnableRowVirtualization 设置为 False,以防止行排序中出现错误:

EnableRowVirtualization="False"

EnableRowVirtualization 属性默认设置为 true。当 EnableRowVirtualization 属性设置为 true 时,DataGrid 不会为绑定数据源中的每个数据项实例化 DataGridRow 对象。相反,DataGrid 仅在需要时创建 DataGridRow 对象,并尽可能地重用它们。 此处参考 MSDN< /a>

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"

The EnableRowVirtualization property is set to true by default. 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. Instead, the DataGrid creates DataGridRow objects only when they are needed, and reuses them as much as it can. MSDN Reference here

鸢与 2024-10-18 23:13:30

这只是另一个答案,为新人或匆忙的人提供几乎复制和粘贴的示例(不鼓励),受到 @GrantA 和 @Johan Larsson 这篇文章中答案的启发(+许多其他人回答了许多帖子)该主题)

  • 您可能不想在列中添加枚举
  • 您不需要重新创建自己的附加属性

    <前><代码><用户控件...

    <网格>



    ...

    ...

    ...


请注意 (ItemsControl.AlternationIndex) 周围的括号 (),如 Fredrik Hedblad 在“检查行是否为奇数”中回答

在此处输入图像描述

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)

  • 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

enter image description here

原谅我要高飞 2024-10-18 23:13:30

使用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>

After some Tests withRowHeaderStyle, the repaired and extended sample from 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>
明明#如月 2024-10-18 23:13:30

使用附加属性,完整源代码位于此处

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

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>

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:

<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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文