Lyn
조회 수 1451 추천 수 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. KBO 에서 잘나가고 싶으면...

    Date2018.11.19 ByLyn Views172
    Read More
  2. [100권프로젝트] 제대로 배우는 Angular 4 [3/100]

    Date2018.10.21 ByLyn Views800
    Read More
  3. [100권프로젝트] 글 모음

    Date2018.10.15 ByLyn Views1376
    Read More
  4. [100권프로젝트] 모두의 딥러닝 [2/100]

    Date2018.10.15 ByLyn Views772
    Read More
  5. [100권프로젝트] 파이썬 동시성 프로그래밍 [1/100]

    Date2018.10.15 ByLyn Views843
    Read More
  6. [100권프로젝트] 기술서적 100권 읽기 들어갑니다 [0/100]

    Date2018.10.15 ByLyn Views609
    Read More
  7. Ubuntu Let's Encrypt renew error "requested nginx plugin does not appear to be installed"

    Date2018.10.07 ByLyn Views539
    Read More
  8. 외주도 안하고 공부도 안하니 이 서버가 무용지물이 되어가고 있군요

    Date2018.09.18 ByLyn Views950
    Read More
  9. 오랫만에 인증서 업데이트와 서버 이전

    Date2018.07.07 ByLyn Views683
    Read More
  10. 요즘 공부를 안하니 쓸게 없네요

    Date2018.06.02 ByLyn Views737
    Read More
  11. Kotlin 공부 후기

    Date2018.02.07 ByLyn Views1466
    Read More
  12. How to IntelliJ IDE VM Setting

    Date2017.12.17 ByLyn Views1045
    Read More
  13. 웹 개발 문서가 MDN으로 통합

    Date2017.12.05 ByLyn Views915
    Read More
  14. WPF Grid 에 표처럼 Border 를 그려보자

    Date2017.08.28 ByLyn Views1451
    Read More
  15. WPF 에서 ListView 의 ScrollBar 버튼 클릭을 프로그램으로 제어 하기

    Date2017.07.22 ByLyn Views2479
    Read More
  16. .net 4.7 의 WPF 가 DX11 기반으로 돌아가네요

    Date2017.06.23 ByLyn Views1067
    Read More
  17. 왜 MemberFunction Pointer 를 cout 으로 출력하면 1이 나올까

    Date2017.03.27 ByLyn Views1916
    Read More
  18. _mm_extract_epi8 함수에 변수 사용시 compile error

    Date2016.12.12 ByLyn Views2343
    Read More
  19. [연속기획UD] 5. Afreeca Streaming

    Date2016.11.27 ByLyn Views2223
    Read More
  20. Enhanced C++ debugging info at VS2012 over

    Date2016.10.22 ByLyn Views2578
    Read More
Board Pagination Prev 1 2 3 4 5 6 7 ... 8 Next
/ 8