Datagrid Paging 구현 질문

안녕하세요 Datagrid에 내가 원하는 데이터를 동적으로 뿌리는것 까지는 했는데요,
해당 데이터가 많아지면 스크롤 무한정하는것도 그렇고해서 페이징 처리를 하려는데
뭔가 찾아봐도 이거다 싶은 내용이 없어서 질문올려봅니다.

datagrid에 뿌릴 데이터는 다음과 같이 선언했습니다.

ObservableCollection<ReportDataSource> datas = new ObservableCollection<ReportDataSource>();

ReportDataSource 클래스는 아래와 같습니다.

public class ReportDataSource
{
        public string SubId { get; set; }
        public string CTag { get; set; }
        public string AddTag { get; set; }
        public int ClickCount { get; set; }
        public int BuyCount { get; set; }
        public int TotalAmount { get; set; }
        public int Profit { get; set; }
        public double ClickPerProfit { get; set; }
        public double ConversionRate { get; set; }
}

DataGrid는 이렇게 만들어 놨습니다.

<DataGrid Grid.Row="3" Margin="-10,10,10,0" Style="{DynamicResource DataGridStyle1}" CellStyle="{DynamicResource DataGridCellStyle1}" ColumnHeaderStyle="{DynamicResource DataGridColumnHeaderStyle1}" RowStyle="{DynamicResource DataGridRowStyle1}" x:Name="reportDataGrid">
    <DataGrid.Columns>
        <DataGridCheckBoxColumn CanUserResize="False" Width="auto" ElementStyle="{StaticResource CheckBoxStyle1}" >
            <DataGridCheckBoxColumn.HeaderTemplate>
                <DataTemplate>
                    <CheckBox/>
                </DataTemplate>
            </DataGridCheckBoxColumn.HeaderTemplate>
        </DataGridCheckBoxColumn>

        <DataGridTextColumn Header="채널ID" IsReadOnly="True" Width="*" Binding="{Binding SubId}"/>
        <DataGridTextColumn Header="페이지 키" IsReadOnly="False" Width="*" Binding="{Binding CTag}"/>
        <DataGridTextColumn Header="페이지 타입" IsReadOnly="True" Width="*" Binding="{Binding AddTag}"/>
        <DataGridTextColumn Header="클릭수" IsReadOnly="True" Width="*" TextBlock.TextAlignment="Center" Binding="{Binding ClickCount}"/>
        <DataGridTextColumn Header="구매건수" IsReadOnly="True" Width="*" TextBlock.TextAlignment="Center" Binding="{Binding BuyCount}"/>
        <DataGridTextColumn Header="총 구매금액" IsReadOnly="True" Width="*" TextBlock.TextAlignment="Center" Binding="{Binding TotalAmount}"/>
        <DataGridTextColumn Header="수익" IsReadOnly="True" Width="*" TextBlock.TextAlignment="Center" Binding="{Binding Profit}"/>
        <DataGridTextColumn Header="클릭당 수익" IsReadOnly="True" Width="*" TextBlock.TextAlignment="Center" Binding="{Binding ClickPerProfit, StringFormat={}{0:0.##}}"/>
        <DataGridTextColumn Header="전환율" IsReadOnly="True" Width="*" TextBlock.TextAlignment="Center" Binding="{Binding ConversionRate, StringFormat={}{0:0.##}%}"/>
    </DataGrid.Columns>
</DataGrid>

Paiging 껍데기도 만들어는 놨습니다…

<Border Grid.Row="4" HorizontalAlignment="Right" BorderBrush="#dee4ec" BorderThickness="1"
                        CornerRadius="5" Padding="5" Background="White" Margin="0 10 10 10">
    <StackPanel Orientation="Horizontal">
        <Button Style="{StaticResource pagingButton}">
            <Icon:PackIconMaterial Kind="ChevronLeft" Style="{StaticResource pagingButtonIcon}"/>
        </Button>

        <Rectangle Width="1" Fill="#dee4ec" Margin="3 7" />

        <Button Style="{StaticResource pagingButton}" Content="1"/>
        <Button Style="{StaticResource pagingButton}" Content="2" Background="#7950f2" Foreground="#ffffff"/>
        <Button Style="{StaticResource pagingButton}" Content="3"/>

        <TextBlock Text="..." Foreground="#6c7682" VerticalAlignment="Center" FontSize="15" Margin="10 0"/>
        <Button Style="{StaticResource pagingButton}" Content="7"/>
        <Button Style="{StaticResource pagingButton}" Content="8"/>
        <Button Style="{StaticResource pagingButton}" Content="9"/>

        <Rectangle Width="1" Fill="#dee4ec" Margin="3 7" />

        <Button Style="{StaticResource pagingButton}">
            <Icon:PackIconMaterial Kind="ChevronRight" Style="{StaticResource pagingButtonIcon}"/>
        </Button>

    </StackPanel>
</Border>

저 페이징버튼 만들어놓은 곳에 페이징기능을 구현하고싶고, 해당 데이터그리드가 기본적으로 헤더클릭으로 정렬이 되는데 그 기능도 유지하고싶습니다. 어떻게 만드는게 좋을 지 조언좀 구해봅니다…

참고로 아래 영상을 보고 껍데기를 구현했습니다.

1 Like

두개의 옵저버컬렉션을 만드시고
하나는 고유 데이터
하나는 조건에 의한 데이터 구성하시고

linq의 스킵과 take를 사용하여

조건에 의한 데이터를 구성하셔도 좋을 것 같습니다

1 Like

감사합니다! 해당키워드로 찾아보고 해보겟습니다

데이터의 페이징 처리를 어떤 방식으로 처리 하실건지를 먼저 정하셔야 합니다.
크게

  1. 로컬 메모리 방식
  2. 서버(DB)에서 페이징 처리

1번 방식으로 하신다면 모든 데이터를 다 불러와서 페이징으로 데이터를 나누어서 보여질뿐 메모리 관점에선 페이징은 아닙니다. 또한 페이징 될때 데이터를 언제 새로 갱신할지 시점도 고려를 해야 합니다.

1번 방식 구현은 @이광석 님 답변 내용처럼
LINQ로 현재 페이지 * 보여질 데이터 갯수 만큼 Skip() 메서드로 데이터를 가져올 시작점을 계산하고 보여질 데이터 갯수 만큼 Take() 메서드로 페이징 처리를 하면 쉽게 처리 가능 합니다.


2번 방식 구현은 클라이언트 입장에선 딱히 처리할 것은 없습니다.
지금 처럼 데이터를 불러올때 데이터를 가져올 수치를 서버에 요청하여 데이터를 로드 시켜주기만 하면 됩니다.
서버측에서는 DB에서 페이징 쿼리로 처리를 하던지 WebAPI 서버를 사용한다면 해당 관련 기술(ORM 등등)로 페이징 처리를 하는 api를 노출 하시면 됩니다.

2 Likes

구현은 1번방식대로 할 것 같습니다. 서버나 DB까지 필요한 프로그램도 아니고 클라이언트에서 데이터를 조작해도 무방한 수준으로 생각되서요

데이터 갱신시점은 데이터를 최초에 불러왔을 때, 필터조건을 통해 데이터 정렬이 변경될 때, 데이터그리드의 헤드컬럼을 클릭하면서 정렬이 변경될 때 말고 또 고려해야할 시점이 있을까요??

1 Like

여러 사람(?)이 이용 되는 서버에서 받아 오는 데이터가 아닌
그냥 로컬 데이터라면 갱신 시점은 딱히 고려할건 없을 것 같습니다.

1 Like