티스토리 뷰
별도의 3rd party 컨트롤을 사용하지 않는 경우 DataGrid를 많이 사용하는데, RowNumber를 출력하는 방법을 찾아보니 MVVM pattern에서 사용하기 쉬운 방법에 대해서 설명되어 있는 것이 없는 것 같아서 간단하게 만들어 보았습니다.
특히, Sort했을 때, Row 추가, 삭제될 때도 계속 번호를 유지 할 수 있으니 개발하실 때 참고하시면 좋을 것 같습니다.
제가 사용한 방법은 Behavior을 이용합니다.
Adding right-aligned row numbers to a DataGridRowHeader in WPF | Magnus Montin
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)
'WPF .NET' 카테고리의 다른 글
개발 시간 단축을 위한 Code Snippet 알아보기 (0) | 2022.02.25 |
---|---|
Microsoft.Toolkit.Mvvm을 이용한 간단한 프레임워크 part2 - Frame Navigation (13) | 2022.02.24 |
Microsoft.Toolkit.Mvvm을 이용한 간단한 프레임워크 part1 (11) | 2022.02.21 |
ListView에 CustomView를 만들고 사용하기 (0) | 2022.02.18 |
ListBox, DataGrid, ListView 차이점 비교 (1) | 2022.02.16 |
- Total
- Today
- Yesterday
- WPF
- windows 11
- LINQ
- #Windows Template Studio
- IOT
- Bot Framework
- kiosk
- #uwp
- C#
- uno platform
- Windows 10
- visual studio 2019
- UWP
- ef core
- dotNETconf
- ComboBox
- XAML
- uno-platform
- #MVVM
- PRISM
- .net
- Visual Studio 2022
- Behavior
- .net 5.0
- Always Encrypted
- MVVM
- Microsoft
- Build 2016
- #prism
- Cross-platform
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |