Lyn
조회 수 1059 추천 수 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 •
?

  1. No Image 21Oct
    by Lyn
    2018/10/21 by Lyn
    Views 563 

    [100권프로젝트] 제대로 배우는 Angular 4 [3/100]

  2. No Image 15Oct
    by Lyn
    2018/10/15 by Lyn
    Views 600 

    [100권프로젝트] 글 모음

  3. No Image 15Oct
    by Lyn
    2018/10/15 by Lyn
    Views 508 

    [100권프로젝트] 모두의 딥러닝 [2/100]

  4. No Image 15Oct
    by Lyn
    2018/10/15 by Lyn
    Views 616 

    [100권프로젝트] 파이썬 동시성 프로그래밍 [1/100]

  5. No Image 15Oct
    by Lyn
    2018/10/15 by Lyn
    Views 352 

    [100권프로젝트] 기술서적 100권 읽기 들어갑니다 [0/100]

  6. No Image 07Oct
    by Lyn
    2018/10/07 by Lyn
    Views 279 

    Ubuntu Let's Encrypt renew error "requested nginx plugin does not appear to be installed"

  7. No Image 18Sep
    by Lyn
    2018/09/18 by Lyn
    Views 762 

    외주도 안하고 공부도 안하니 이 서버가 무용지물이 되어가고 있군요

  8. No Image 07Jul
    by Lyn
    2018/07/07 by Lyn
    Views 474 

    오랫만에 인증서 업데이트와 서버 이전

  9. No Image 02Jun
    by Lyn
    2018/06/02 by Lyn
    Views 542 

    요즘 공부를 안하니 쓸게 없네요

  10. No Image 07Feb
    by Lyn
    2018/02/07 by Lyn
    Views 1165 

    Kotlin 공부 후기

  11. No Image 17Dec
    by Lyn
    2017/12/17 by Lyn
    Views 750 

    How to IntelliJ IDE VM Setting

  12. No Image 05Dec
    by Lyn
    2017/12/05 by Lyn
    Views 685 

    웹 개발 문서가 MDN으로 통합

  13. No Image 28Aug
    by Lyn
    2017/08/28 by Lyn
    Views 1059 

    WPF Grid 에 표처럼 Border 를 그려보자

  14. No Image 22Jul
    by Lyn
    2017/07/22 by Lyn
    Views 2171 

    WPF 에서 ListView 의 ScrollBar 버튼 클릭을 프로그램으로 제어 하기

  15. No Image 23Jun
    by Lyn
    2017/06/23 by Lyn
    Views 838 

    .net 4.7 의 WPF 가 DX11 기반으로 돌아가네요

  16. No Image 27Mar
    by Lyn
    2017/03/27 by Lyn
    Views 1670 

    왜 MemberFunction Pointer 를 cout 으로 출력하면 1이 나올까

  17. _mm_extract_epi8 함수에 변수 사용시 compile error

  18. [연속기획UD] 5. Afreeca Streaming

  19. No Image 22Oct
    by Lyn
    2016/10/22 by Lyn
    Views 2386 

    Enhanced C++ debugging info at VS2012 over

  20. No Image 01Oct
    by Lyn
    2016/10/01 by Lyn
    Views 4313 

    사이트에서 http2 프로토콜을 지원 하기 시작 했습니다.

Board Pagination Prev 1 2 3 4 5 6 7 ... 8 Next
/ 8