Lyn
조회 수 947 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

WPF 에는 표처럼 오브젝트를 배치할 수 있는 Grid 라는 Layout 컨테이너가 존재한다

 

그런데 이 컨테이너는 Layout 만 잡아 줄 뿐 표처럼 선을 그려주는 기능은 없... 진 않지만 내장되어 있는 ShowGridLines 는 사실상 UI 디버깅 용도 외에는 쓰기 힘들정도로 심각하게 기능이 구리다.

 

그래서 유명하신 정성태님이 아래와 같은 글을 쓰셧다

 

WPF - Grid 컨트롤의 ShowGridLine 개선

 

윗 링크의 글을 보면 아래와 같은 부분이 있다

 

"생각 자체는 그리 어렵지 않습니다. 예를 들어, 가로선을 그을 때(Row별로) 컬럼 단위만큼 그리며 진행하다가 다음번 그려야 될 곳이 RowSpan으로 되어 있으면 그 구획은 긋지 말고 건너뛰면 됩니다. 세로선도 마찬가지겠지요."

 

그리고 해당 컨트롤을 구현한 솔루션이 링크되어 있는데... 실제로는 구현이 반대로 되어 있다. Element 를 뒤져 가며 Span 된 부분을 건너뛰는 것이 아니라 Span 이 아닌 부분을 그리는 식으로. 사실 이렇게 하더라도 저 위 샘플에선 전혀 문제가 없이 나오는데... 문제는 저 Grid에 어떤 Element 도 없는 "빈칸" 이 존재할 경우 그 부분은 아예 Border 가 그려지지 않는다는 것이다...

 

그래서 위에 인용한 글 대로 Skip 하는 식으로 변형을 해서 쓰기로 했고, 그 코드를 공개한다

 

public class BorderGrid : Grid
{
    public BorderGrid() : base()
    {

    }

    public Thickness CellPadding
    {
        get
        {
            return (Thickness)this.GetValue(CellPaddingProperty);
        }
        set
        {
            this.SetValue(CellPaddingProperty, value);
        }
    }

    public static readonly DependencyProperty CellPaddingProperty =
        DependencyProperty.Register("CellPadding", typeof(Thickness), typeof(BorderGrid),
            new FrameworkPropertyMetadata(new Thickness(0.0, 0.0, 0.0, 0.0), FrameworkPropertyMetadataOptions.AffectsArrange,
            OnCellPaddingChanged)
        );

    static void OnCellPaddingChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
    {
        BorderGrid grid = (dependencyObject as BorderGrid);
        foreach (UIElement uiElement in grid.Children)
        {
            ApplyMargin(grid, uiElement);
        }
    }

    protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
    {
        FrameworkElement childElement = visualAdded as FrameworkElement;
        ApplyMargin(this, childElement);

        base.OnVisualChildrenChanged(visualAdded, visualRemoved);
    }

    public static void ApplyMargin(BorderGrid PaddingGrid, UIElement element)
    {
        FrameworkElement childElement = element as FrameworkElement;
        Thickness cellPadding = PaddingGrid.CellPadding;

        BorderGrid childPaddingGrid = element as BorderGrid;
        if (childPaddingGrid != null)
        {
            childPaddingGrid.CellPadding = cellPadding;
        }
        else
        {
            if (childElement != null)
            {
                childElement.Margin = cellPadding;
            }
        }
    }

    Pen line = new Pen(Brushes.Black, 2);
    protected override void OnRender(System.Windows.Media.DrawingContext dc)
    {
        base.OnRender(dc);

        BorderGrid customGrid = this.Parent as BorderGrid;
        if (customGrid == null)
        {
            dc.DrawRectangle(null, line, new Rect(0, 0, this.ActualWidth, this.ActualHeight));
        }

        double linePoint = 0;
        double posFrom = 0.0;
        double posTo = 0.0;

        int rowCount = Math.Max(this.RowDefinitions.Count, 1);
        int columnCount = Math.Max(this.ColumnDefinitions.Count, 1);

        bool[,] rowCellIgnoreStatus;
        bool[,] columnCellIgnoreStatus;

        GetRowLineCellStatus(rowCount, columnCount, out rowCellIgnoreStatus, out columnCellIgnoreStatus);

        if (this.ColumnDefinitions.Count != 0)
        {
            for (int row = 0; row < rowCount - 1; row++)
            {
                var r = this.RowDefinitions[row];

                linePoint += r.ActualHeight;
                for (int column = 0; column < columnCount; column++)
                {
                    bool ignoreLine = rowCellIgnoreStatus[row + 1, column];
                    posTo += this.ColumnDefinitions[column].ActualWidth;

                    if (ignoreLine == false)
                    {
                        dc.DrawLine(line, new Point(posFrom, linePoint), new Point(posTo, linePoint));
                    }

                    posFrom = posTo;
                }

                posFrom = 0.0;
                posTo = 0.0;
            }
        }

        linePoint = 0;
        posFrom = 0.0;
        posTo = 0.0;

        if (this.RowDefinitions.Count != 0)
        {
            for (int column = 0; column < columnCount - 1; column++)
            {
                var r = this.ColumnDefinitions[column];

                linePoint += r.ActualWidth;
                for (int row = 0; row < rowCount; row++)
                {
                    bool ignoreLine = columnCellIgnoreStatus[row, column + 1];
                    posTo += this.RowDefinitions[row].ActualHeight;

                    if (ignoreLine == false)
                    {
                        dc.DrawLine(line, new Point(linePoint, posFrom), new Point(linePoint, posTo));
                    }

                    posFrom = posTo;
                }

                posTo = 0.0;
                posFrom = 0.0;
            }
        }
    }

    private void GetRowLineCellStatus(int rowCount, int columnCount, out bool[,] rowCellIgnoreStatus, out bool[,] columnCellIgnoreStatus)
    {
        rowCellIgnoreStatus = new bool[rowCount, columnCount];
        columnCellIgnoreStatus = new bool[rowCount, columnCount];

        foreach (UIElement element in this.Children)
        {
            int row = Grid.GetRow(element);
            int column = Grid.GetColumn(element);

            int spanCount = Grid.GetColumnSpan(element);

            for (int span = 1; span < spanCount; span++)
            {
                try
                {
                    columnCellIgnoreStatus[row, column + span] = true;
                }
                catch (Exception)
                {
                    //
                }
            }

            spanCount = Grid.GetRowSpan(element);
            for (int span = 1; span < spanCount; span++)
            {
                rowCellIgnoreStatus[row + span, column] = true;
            }
        }
    }
}

 

TAG •
?

List of Articles
번호 제목 글쓴이 날짜 조회 수
143 [100권프로젝트] 프로그래밍의 정석 - 프로그래머가 반드시 알아야할 101가지 원리원칙 [7/100] file Lyn 2019.01.03 87
142 [100권프로젝트] Node.js 마이크로 서비스 코딩공작소 [6/100] file Lyn 2019.01.03 157
141 [100권프로젝트] Java 9 모듈 프로그래밍 [5/100] file Lyn 2019.01.03 62
140 [100권프로젝트] 스타트 스프링 부트 [4/100] file Lyn 2018.12.23 113
139 [독서후기] 말레우스 말레피카룸 - 마녀를 심판하는 망치 Lyn 2018.11.22 169
138 KBO 에서 잘나가고 싶으면... Lyn 2018.11.19 158
137 [100권프로젝트] 제대로 배우는 Angular 4 [3/100] file Lyn 2018.10.21 341
136 [100권프로젝트] 글 모음 Lyn 2018.10.15 274
135 [100권프로젝트] 모두의 딥러닝 [2/100] file Lyn 2018.10.15 282
134 [100권프로젝트] 파이썬 동시성 프로그래밍 [1/100] file Lyn 2018.10.15 393
133 [100권프로젝트] 기술서적 100권 읽기 들어갑니다 [0/100] Lyn 2018.10.15 246
132 Ubuntu Let's Encrypt renew error "requested nginx plugin does not appear to be installed" Lyn 2018.10.07 204
131 외주도 안하고 공부도 안하니 이 서버가 무용지물이 되어가고 있군요 Lyn 2018.09.18 662
130 오랫만에 인증서 업데이트와 서버 이전 Lyn 2018.07.07 421
129 요즘 공부를 안하니 쓸게 없네요 Lyn 2018.06.02 481
128 Kotlin 공부 후기 Lyn 2018.02.07 1023
127 How to IntelliJ IDE VM Setting Lyn 2017.12.17 678
126 웹 개발 문서가 MDN으로 통합 Lyn 2017.12.05 640
» WPF Grid 에 표처럼 Border 를 그려보자 Lyn 2017.08.28 947
124 WPF 에서 ListView 의 ScrollBar 버튼 클릭을 프로그램으로 제어 하기 Lyn 2017.07.22 2055
Board Pagination Prev 1 2 3 4 5 6 7 ... 8 Next
/ 8