WPF - Grid 컨트롤의 ShowGridLine 개선
지난번에는 HTML 테이블의 Cell Padding에 해당하는 기능을 구현해 보았는데요.
WPF - CellPadding 속성을 구현하는 Grid Layout
; https://www.sysnet.pe.kr/2/0/734
역시나, HTML Table 태그를 사용해보신 분들은 또 한 가지 아쉬운 기능이 있을 것입니다. 바로 Cell 간의 Border 속성이 그것인데요.
예를 들어, 다음과 같은 HTML Table의 경우,
<table style="width: 300px; height: 300px;" border="1">
<tr>
<td> </td>
<td> </td>
<td rowspan=2> </td>
</tr>
<tr>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td colspan=2> </td>
</tr>
</table>
아래와 같은 식으로 나오게 됩니다.
[그림 1: Border가 지정된 HTML Table]
이제 WPF에서 제공되는 Grid Panel과 비교해 볼까요?
다행히, WPF Grid 역시 Border와 비슷한 기능을 제공합니다. "ShowGridLines" 의존 속성을 지원하는데, 이를 지정하면 다음과 같은 식으로 보이게 됩니다.
[그림 2: ShowGridLines="True"가 지정된 Grid]
불행히도, 보시는 것처럼 ShowGridLines 속성이 왜 있을까 하는 의문이 들 정도입니다. 사실, Microsoft에서는 이 기능을 사용하지 말라고 권고하고 있습니다.
.NET Framework Class Library - Grid.ShowGridLines Property
; https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.grid.showgridlines#System_Windows_Controls_Grid_ShowGridLines
Only dotted lines are available because this property is intended as a design tool to debug layout problems and is not intended for use in production quality code. If you want lines inside a Grid, style the elements within the Grid to have borders.
스타일로 해결하라는데, ... 그건 디자인 잘 하시는 분들이 해결해 주시고. ^^ 저는 프로그래밍으로 접근해 보겠습니다.
일단, 검색을 해보죠.
How can I change the color of the gridlines of a Grid in WPF?
; http://stackoverflow.com/questions/606220/how-can-i-change-the-color-of-the-gridlines-of-a-grid-in-wpf
위의 글은 원인은 분석하였으나 답을 내주지 못했습니다. 그래서 좀 더 ^^ 찾아보면,
WPF Grid Question
; http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/74e36c60-b93a-47c7-8214-79669ec6b121/
오... 그나마 괜찮은 대답입니다.
코드는 그저 Grid에 OnRender 부분만 다음과 같이 재정의해주면 됩니다.
public class CustomGrid : Grid
{
Pen line = new Pen(Brushes.Black, 1);
protected override void OnRender(System.Windows.Media.DrawingContext dc)
{
base.OnRender(dc);
dc.DrawRectangle(null, line, new Rect(0,0,this.ActualWidth, this.ActualHeight));
double height = 0;
foreach (var r in this.RowDefinitions)
{
height += r.ActualHeight;
dc.DrawLine(line, new Point(0, height), new Point(this.ActualWidth,height));
}
double width = 0;
foreach (var c in this.ColumnDefinitions)
{
width += c.ActualWidth;
dc.DrawLine(line, new Point(width, this.ActualHeight), new Point(width, 0));
}
}
}
와~~~ 간단하지요. ^^ 그런데, 정작 적용해 보면 다양한 상황을 고려하지 않았음을 알 수 있습니다. 예를 들어, 아래의 그림과 같이 나옵니다.
[그림 3: RowSpan/ColumnSpan이 고려되지 않은 Cell Border]
그럼, 이 부분을 다듬으면 문제는 해결이 되는데요. 생각 자체는 그리 어렵지 않습니다. 예를 들어, 가로선을 그을 때(Row별로) 칼럼 단위만큼 그리며 진행하다가 다음번 그려야 될 곳이 RowSpan으로 되어 있으면 그 구획은 긋지 말고 건너뛰면 됩니다. 세로선도 마찬가지겠지요.
그렇게 생각한 데로 구현해서 보정하면, 최종적으로 아래와 같이 나옵니다. 이 정도면... 괜찮지 않나요! ^^
[그림 4: RowSpan/ColumnSpan 영역을 고려한 Cell Border]
보정된 소스 코드는 첨부된 솔루션 압축 파일에 있습니다. (2023-04-20: 덧글의 Lyn 님의 소스코드가 반영됐습니다.)
[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]