티스토리 뷰

WPF .NET

DataGrid에 Row번호를 출력하기

kaki104 2022. 2. 23. 10:00
반응형

별도의 3rd party 컨트롤을 사용하지 않는 경우 DataGrid를 많이 사용하는데, RowNumber를 출력하는 방법을 찾아보니 MVVM pattern에서 사용하기 쉬운 방법에 대해서 설명되어 있는 것이 없는 것 같아서 간단하게 만들어 보았습니다.

 

특히, Sort했을 때, Row 추가, 삭제될 때도 계속 번호를 유지 할 수 있으니 개발하실 때 참고하시면 좋을 것 같습니다.

제가 사용한 방법은 Behavior을 이용합니다.

 

Adding right-aligned row numbers to a DataGridRowHeader in WPF | Magnus Montin

 

Adding right-aligned row numbers to a DataGridRowHeader in WPF

This post provides an example of how you can right-align or centre the text in a DataGridRowHeader in a DataGrid in WPF using Visual Studio 2012 or later. It also explains how you can display the c…

blog.magnusmontin.net

Row 번호와 관련된 blog가 있어서 참고 하시면 더 좋을 것 같습니다. 

1. 개발환경

Windows 11 (Windows 10 도 가능)

Visual Studio 2022 (Visual Studio 2019 가능)

.NET 5.0

Microsoft.Xaml.Behaviors.Wpf 1.1.39 : Behavior를 만들어야 하기 때문에 반드시 필요한 Nuget package입니다.

2. DataGridBehavior.cs

using Microsoft.Xaml.Behaviors;
using System.Windows.Controls;

namespace DataGridNumberColumn
{
    /// <summary>
    /// DataGridBehavior
    /// </summary>
    public class DataGridBehavior : Behavior<DataGrid>
    {
        /// <summary>
        /// ShowRowNumber
        /// </summary>
        public bool ShowRowNumber { get; set; }

        protected override void OnAttached()
        {
            if (ShowRowNumber)
            {
                AssociatedObject.RowHeaderWidth = 40;
                AssociatedObject.LoadingRow += AssociatedObject_LoadingRow;
                AssociatedObject.UnloadingRow += AssociatedObject_UnloadingRow;
            }
        }
        /// <summary>
        /// 로우 언로딩 이벤트 - 삭제시
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AssociatedObject_UnloadingRow(object sender, DataGridRowEventArgs e)
        {
            RefreshRowNumber();
        }
        /// <summary>
        /// 전체 번호 다시 출력
        /// </summary>
        private void RefreshRowNumber()
        {
            foreach (var item in AssociatedObject.Items)
            {
                var row = AssociatedObject.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
                if (row == null)
                {
                    continue;
                }
                row.Header = row.GetIndex() + 1;
            }
        }
        /// <summary>
        /// Row 로딩 이벤트
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AssociatedObject_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.Header = e.Row.GetIndex() + 1;
        }

        protected override void OnDetaching()
        {
            if (ShowRowNumber)
            {
                AssociatedObject.LoadingRow -= AssociatedObject_LoadingRow;
                AssociatedObject.UnloadingRow -= AssociatedObject_UnloadingRow;
            }
        }
    }
}

3. MainWindow.xaml

생성한 Behavior를 DataGrid에 연결합니다.

<Window
    x:Class="DataGridNumberColumn.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:DataGridNumberColumn"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    Loaded="Window_Loaded"
    mc:Ignorable="d">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal">
            <Button
                Margin="5,0,0,0"
                Click="Add_Click"
                Content="Add" />
            <Button
                Margin="5,0,0,0"
                Click="Remove_Click"
                Content="Remove" />
        </StackPanel>
        <DataGrid
            x:Name="PeopleDataGrid"
            Grid.Row="1"
            AutoGenerateColumns="False"
            IsReadOnly="False">
            <!--  생성한 Behavior 연결  -->
            <b:Interaction.Behaviors>
                <local:DataGridBehavior ShowRowNumber="True" />
            </b:Interaction.Behaviors>
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Name}" Header="Name" />
                <DataGridTextColumn Binding="{Binding Age}" Header="Age" />
                <DataGridTextColumn Binding="{Binding Address}" Header="Address" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

4. MainWindow.xaml.cs

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;

namespace DataGridNumberColumn
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private IList<Person> _persons;

        public MainWindow()
        {
            InitializeComponent();

            _persons = new ObservableCollection<Person>
            {
                new Person{ Name = "kaki104", Age = 11, Address = "Seoul1" },
                //...............
                new Person{ Name = "kaki0143", Age = 150, Address = "Seoul140" },
            };
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            PeopleDataGrid.ItemsSource = _persons;
        }

        private void Add_Click(object sender, RoutedEventArgs e)
        {
            _persons.Add(new Person { Name = "Add1", Age = 41, Address = "Seoul99" });
        }

        private void Remove_Click(object sender, RoutedEventArgs e)
        {
            if (PeopleDataGrid.SelectedItem != null)
            {
                _persons.Remove(PeopleDataGrid.SelectedItem as Person);
            }
        }
    }
}

5. 실행 화면

시작 화면

Address로 정렬

Add 버튼 눌러서 한줄 추가

10번 아이템 삭제 전

10번 아이템 삭제 후

6. 부족한 부분 및 주의사항

혹시라도 번호가 뒤죽박죽되는 경우에는 가상화를 끄고 하시면 될 것 같습니다.

RowHeaderTemplate이나 RowHeaderStyle을 이용하면 숫자를 오른쪽 정렬을할 수 있습니다.

7. 소스

DataGridNumberColumn 프로젝트를 실행시키시면 됩니다.

원래 Column으로 만들려고 했는데..만들다보니 않되더군요;;

WpfTest/DataGridNumberColumn at master · kaki104/WpfTest (github.com)

 

GitHub - kaki104/WpfTest

Contribute to kaki104/WpfTest development by creating an account on GitHub.

github.com

 

반응형
댓글