Winforms윈폼 WPF Datagrid 바꾸기 및 반전을 위한 4단계
페이지 정보
작성자 GrapeCity 작성일 2022-03-01 13:38 조회 1,493회 댓글 0건본문
첨부파일
관련링크
Datagrid는 열은 세로로, 행은 가로로 표시되는 표 형식으로 데이터를 시각화하는 데 일반적으로 사용됩니다. 경우에 따라 데이터를 가로로 표시해야 할 수 있습니다.
행이 열이 되고 열이 행이 되도록 매트릭스를 바꿔 ComponentOne FlexGrid를 사용하여 반전된 WPF Datagrid를 만드는 방법을 살펴보겠습니다.
이 샘플 자습서에서는 C1.WPF.Grid 패키지의 NuGet에서 얻을 수 있는 WPF datagrid UI 컨트롤인 .NET 6 FlexGrid를 사용합니다.
1단계: FlexGrid 확장 만들기
FlexGrid 확장 만들기는 앱 전체에서 재사용 가능한 FlexGrid를 만들고 키 이벤트를 재정의하는 간소화된 방법입니다. 바뀐 Datagrid 확장은 사용자가 클릭하는 셀 유형 및 범위를 바꿀 수 있도록 OnCellTapped 이벤트를 재정의합니다.
using C1.WPF.Core; using C1.WPF.Grid; public class TransposedGrid : FlexGrid { public TransposedGrid() { CellFactory = new TransposedCellFactory(); MergeManager = new TransposedMergeManager(); } protected override void OnCellTapped(GridCellType cellType, GridCellRange range, C1TappedEventArgs te) { if (cellType == GridCellType.RowHeader) { base.OnCellTapped(TransposeCellType(cellType), TransposeRange(range), te); } else { base.OnCellTapped(cellType, range, te); } } public static GridCellType TransposeCellType(GridCellType cellType) { if (cellType == GridCellType.ColumnHeader) return GridCellType.RowHeader; else if (cellType == GridCellType.RowHeader) return GridCellType.ColumnHeader; return cellType; } public static GridCellRange TransposeRange(GridCellRange range) { return new GridCellRange(range.Column, range.Row, range.Column2, range.Row2); } }
또한 바뀐 FlexGrid 확장은 행과 열을 교환하여 화면표시를 바꾸는 사용자 정의 Cell Factory 및 병합 관리자를 시작합니다. 다음으로 클래스를 정의합니다.
2단계: 바뀌는 Cell Factory 정의
Cell Factory는 값 변환기와 유사하지만 FlexGrid 컨트롤에 특별합니다. ICellFactory는 셀을 나타내는 FrameworkElement 개체를 생성하는 데 사용되며 스크롤할 때 UI 가상화에 최적화되어 있습니다. 제시하는 샘플에서 TransposedCellFactory는 기본적으로 모든 목적 및 상호 작용에 맞춰 행과 열 정보를 바꿔 FlexGrid가 바뀐 그리드로 표시되고 스크롤됩니다.
internal class TransposedCellFactory : GridCellFactory { public override int ColumnHeaderRowsCount => base.RowHeaderColumnsCount; public override int RowHeaderColumnsCount => base.ColumnHeaderRowsCount; public override int CellsColumnsCount => base.CellsRowsCount; public override int CellsRowsCount => base.CellsColumnsCount; protected override ColumnInfo GetColumnInfo(bool isHeader, int column) { if (isHeader) { return new ColumnInfo(Grid.DefaultRowHeaderColumnWidth, Grid.MinColumnWidth, Grid.MaxColumnWidth, true); } else { return new ColumnInfo(Grid.DefaultColumnWidth, Grid.MinColumnWidth, Grid.MaxColumnWidth, true); } } protected override RowInfo GetRowInfo(bool isHeader, int row) { return DefaultRow; } public override void PrepareCell(GridCellType cellType, GridCellRange range, GridCellView cell, Thickness internalBorders) { base.PrepareCell(TransposedGrid.TransposeCellType(cellType), TransposedGrid.TransposeRange(range), cell, internalBorders); } public override object GetCellContentType(GridCellType cellType, GridCellRange range) { return base.GetCellContentType(TransposedGrid.TransposeCellType(cellType), TransposedGrid.TransposeRange(range)); } public override FrameworkElement CreateCellContent(GridCellType cellType, GridCellRange range, object cellContentType) { return base.CreateCellContent(TransposedGrid.TransposeCellType(cellType), TransposedGrid.TransposeRange(range), cellContentType); } public override void BindCellContent(GridCellType cellType, GridCellRange range, FrameworkElement cellContent) { base.BindCellContent(TransposedGrid.TransposeCellType(cellType), TransposedGrid.TransposeRange(range), cellContent); } public override void UnbindCellContent(GridCellType cellType, GridCellRange range, FrameworkElement cellContent) { base.UnbindCellContent(TransposedGrid.TransposeCellType(cellType), TransposedGrid.TransposeRange(range), cellContent); } protected override bool CanSetColumnWidth(bool isHeader, int column) { return false; } protected override bool CanSetRowHeight(bool isHeader, int row) { return false; } public override bool AllowEditing(GridCellRange range) { return base.AllowEditing(TransposedGrid.TransposeRange(range)); } public override FrameworkElement CreateCellEditor(GridCellRange range) { return base.CreateCellEditor(TransposedGrid.TransposeRange(range)); } public override void OnEditEnded(GridCellRange range, FrameworkElement editor, bool editCancelled) { base.OnEditEnded(TransposedGrid.TransposeRange(range), editor, editCancelled); } }
보시다시피 이 FlexGrid 확장의 TransposeCellType 및 TransposeRange 메서드는 모든 이벤트 재정의 내에서 호출되어 바뀐 그리드를 만듭니다. 병합 관리자 클래스는 셀 병합 로직에 사용되며 역시 바뀌어야 합니다.
public class TransposedMergeManager : GridMergeManager { public override GridCellRange GetMergedRange(GridCellType cellType, GridCellRange range) { return TransposedGrid.TransposeRange(base.GetMergedRange(TransposedGrid.TransposeCellType(cellType), TransposedGrid.TransposeRange(range))); } }
3단계: XAML로 TransposedGrid 시작
확장을 만들었으므로 이제 프로젝트를 빌드하고 XAML 페이지에서 로컬 컴포넌트를 만들어 보겠습니다. 확장 및 Cell Factory가 행 및 열 로직을 바꾸더라도 이는 런타임에만 적용됩니다. API의 나머지 부분에서는 계속해서 셀의 세로 스택으로 "열"을 사용하고 "행"은 가로 셀을 나타냅니다.
이러한 경우 HeadersVisibility를 "Row"로 설정하고 DefaultRowHeaderColumnWidth를 "100"과 같이 더 큰 값으로 설정해야 합니다. 그러면 그리드의 왼쪽 가장자리를 따라 고정된 열 헤더(기술적으로는 여전히 행 헤더)가 생깁니다.
<local:TransposedGrid x:Name="flexGrid" AutoGenerateColumns="True" ColumnHeaderBackground="LightGray" DefaultRowHeaderColumnWidth="100" GridLinesVisibility="All" HeadersVisibility="Row" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible"> </local:TransposedGrid></td>
4단계: Datasource 및 빌드 설정
마지막으로, 원하는 접근 방식을 사용하여 FlexGrid를 데이터 바인딩합니다. XAML로 구성을 더 세부적으로 제어하도록 열을 자동으로 생성하기보다는 XAML로 열을 정의하려고 할 수 있습니다. FlexGrid Datasource를 설정하기 위해 ItemsSource 속성을 비즈니스 개체 컬렉션 또는 열거 가능한 목록으로 설정합니다. 를 확인하세요.
회전 변환 및 RTL을 사용하는 대체 접근 방식
저는 RightToLeft(RTL) 흐름 방향 및 기본 변환을 사용하여 FlexGrid를 바꾸는 대체 접근 방식으로 시도해 보았습니다. 회전 변환만 사용하면 그리드가 바뀌고 스크롤 막대의 위치가 잘못됩니다. RTL은 스크롤 막대 문제를 해결하지만 더 많은 문제를 일으킵니다. 즉, RTL로 인해 스크롤 막대 외 모든 것이 대칭 이동됩니다. 하지만 몇 가지 추가 눈금 변환을 사용하여 대부분의 항목이 예상대로 동작하도록 만들 수 있습니다.
저는 위에서 설명한 Cell Factory 접근 방식을 사용할 것을 추천해 드리지만 Cell Factory 솔루션이 효과가 없는 경우에는 이 대안 샘플을 다운로드하여 어떻게 되는지 살펴보는 것도 좋습니다.
지금 바로 ComponentOne을 다운로드하여 직접 테스트해보세요!
댓글목록
등록된 댓글이 없습니다.