검색결과 리스트
WPF에 해당되는 글 15건
글
Expanding Canvas 만들기
목차
앞선 포스팅(http://crystalcube.co.kr/153)에서 DraggableCanvas 를 만들어 보았습니다. 그런데 조금 불편한게 있습니다.
Canvas 밖으로 드래그를 했을 때, Canvas 가 자동으로 늘어나지 않기 때문에 찾을 방법이 없어집니다. 윈도우 자체의 크기를 늘려서 Canvas 를 늘리지 않는 한 말이죠.
개요
Canvas 의 Element(Child)가 Canvas 밖으로 빠져나가면, Grid 처럼 Canvas 의 사이즈가 거기에 맞게 커지도록 해 보겠습니다. 즉 확장되는 캔버스 라고 할 수 있겠네요.
이 방법에 대해서 고민을 많이 해 보았습니다.
1 차 시도.
Canvas 의 Template 을 손댄뒤, 크기를 Binding 을 통해 무언가 시도해 본다.
여러가지 해 보았지만, 깔끔하게 떨어지지 않더군요... 다른 방법을 찾아봐야 겠습니다.
2 차 시도.
Canvas 의 MeasureOverride 에서 크기를 다시 계산한다.
MeasureOverride 함수가 적절한 시기에 계속해서 호출되어야 하는데, 이게 안됩니다.
OnRender 함수가 호출이 매번 되는 것도 아니고...
어디선가 Child 의 위치/크기가 변경될때마다 열심히 호출해 주어야 하는데 적절한 위치가 없네요.
3 차 시도.
MeasureOverride 를 이용하되, PropertyMetaData 를 Override 하여, AffectsParentMeasure 옵션을 넣어준다.
잘 동작합니다 :)
어차피 Canvas 안에서 위치가 이동하려면, Canvas.Left, Canvas.Top, Canvas.Right, Canvas.Bottom 들이 바뀌어야 하지요.(물론 이외의 방법도 있을 수 있기에,, 고려해야 하지만, 여기서는 무시하도록 하겠습니다 -_-)
즉, LeftProperty, RightProperty 등을 override 해 주면 됩니다.
코드는 다음과 같습니다.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using SW.Common.Extensions;
namespace SW.Common.Controls
{
public class ExpandingCanvas : Canvas
{
static ExpandingCanvas()
{
if(DesignerProperties.GetIsInDesignMode(new DependencyObject()) == false)
{
Canvas.LeftProperty.OverrideMetadata(typeof(UIElement), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsParentMeasure));
Canvas.TopProperty.OverrideMetadata(typeof(UIElement), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsParentMeasure));
Canvas.RightProperty.OverrideMetadata(typeof(UIElement), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsParentMeasure));
Canvas.BottomProperty.OverrideMetadata(typeof(UIElement), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsParentMeasure));
}
DefaultStyleKeyProperty.OverrideMetadata(typeof(ExpandingCanvas), new FrameworkPropertyMetadata(typeof(ExpandingCanvas)));
}
protected override Size MeasureOverride(Size constraint)
{
List<FrameworkElement> children = this.FindVisualDescendants<FrameworkElement>().ToList();
if (children.Count <= 0) { return base.MeasureOverride(constraint); }
double right = 0.0;
double bottom = 0.0;
foreach (FrameworkElement child in children)
{
Point p = child.TranslatePoint(new Point(child.ActualWidth, child.ActualHeight), this);
right = Math.Max(right, p.X);
bottom = Math.Max(bottom, p.Y);
}
if (right <= 0.0 || bottom <= 0.0) { return base.MeasureOverride(constraint); }
return new Size(right, bottom);
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
this.InvalidateMeasure();
base.OnRenderSizeChanged(sizeInfo);
}
}
}
위 코드에서 DesignMode 일때 건너뛴 이유는, 이렇게 안하면 Designer 에서 오류가 발생합니다. 이미 해당 type 에 대해서 metadata 가 선언되었다는 오류입니다. Canvas.LeftProperty 등은 Dependency Property 가 아니라, Attached Property 입니다. 그렇기 때문에 첫번째 파라미터의 type 이 ExpandingCanvas 면 동작하지 않습니다. 여기 달라붙는 Child 들의 type 을 적어주어야 하기 때문이죠. 그래서 UIElement 의 타입을 넣어주어야 하는데, 그러면 위 이유로 오류가 납니다. -_-; 물론 실행시에는 잘 동작합니다. 해결 방법을 모르겠네요.
디자이너에서도 오류없이 잘 보이고, 실행도 잘 되는 방법을 말이죠.
아시는분은 답변 부탁드립니다 :)
<Window x:Class="TestMain.ExpandingCanvasTest"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sw="http://wpf.sungwook.kim/common"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Title="ExpandingCanvasTest" Height="300" Width="300">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<sw:ExpandingCanvas x:Name="PART_ExpandingCanvas">
<Grid Background="Yellow" Width="100" Height="100">
<i:Interaction.Behaviors>
<sw:DragOnCanvasBehavior BaseElement="{Binding ElementName=PART_ExpandingCanvas}"></sw:DragOnCanvasBehavior>
</i:Interaction.Behaviors>
</Grid>
</sw:ExpandingCanvas>
</ScrollViewer>
</Window>
위에서 사용한 DragOnCanvasBehavior 는 이전 포스팅을 참고하시기 바랍니다.
'Microsoft > WPF' 카테고리의 다른 글
Expanding Canvas 만들기 2 (0) | 2014.11.16 |
---|---|
격자 배경 그리기 (0) | 2014.11.14 |
Drag Canvas 만들기 (0) | 2014.11.13 |
TreeView Template 을 통한 Canvas 만들기 (1) | 2014.11.12 |
MEF(Managed Extensibility Framework) (2) | 2014.05.19 |
RECENT COMMENT