silverlight
Behavior 만들기
Min-gu, Kim
2009. 6. 18. 17:58
Silverlight 3 에서는 Behavior 를 지원합니다.
그리고, DependencyObject에 Behavior를 Add 된 경우 실행 되는 Behavior.OnAttached 메소드를 구현(override)하여, Behavior를 정의합니다.
[Category("카테고리명")] 으로 Property에 대한 Category를 지정하게 되면, Microsoft Expression Blend 3 Preivew 상에서 다음 그림에서 처럼 표시 됩니다.
Behavior란 사전적인 해석에서 알 수 있듯이, 동작을 뜻합니다. 이 동작이란 것은, Dependency Object의 동작이 될 수도 있고, FrameworkElement의 Event에 대한 Trigger가 될 수 있습니다.
Behavior를 Silverlight 3 에서 구현하는 방법 입니다.
1. Dependency object 의 Behavior 정의
우선, Dependency object의 Behavior를 정의 하기 위해서는,
Program Files > Microsoft Expression > Bledn 3 Preview > Libraries > Silverlight > Microsoft.Expression.Interativity.dll 을 참조 추가 해야 합니다.
참조 추가를 한 뒤, Microsoft.Expression.Interactivity.dll 에 있는 Behavior<T> : where T : DependencyObject 를 상속 받아서 Behavior 클래스를 만듭니다.
public class DragBehavior : Microsoft.Expression.Interactivity.Behavior<UIElement>
{
}
{
}
그리고, DependencyObject에 Behavior를 Add 된 경우 실행 되는 Behavior.OnAttached 메소드를 구현(override)하여, Behavior를 정의합니다.
public class DragBehavior : Behavior<UIElement>
{
private bool isDragging = false;
private UIElement attachedElement;
private UserControl parent;
Point lastPosition;
TranslateTransform translatePosition;
protected override void OnAttached()
{
attachedElement = this.AssociatedObject;
parent = Application.Current.RootVisual as UserControl;
attachedElement.MouseLeftButtonDown += new MouseButtonEventHandler(MouseIsDown);
attachedElement.MouseLeftButtonUp += new MouseButtonEventHandler(MouseIsUp);
attachedElement.MouseMove += new MouseEventHandler(MouseIsMoving);
}
void MouseIsMoving(object sender, MouseEventArgs e)
{
if (isDragging)
{
Point currentPosition = e.GetPosition(parent);
double dX = currentPosition.X - lastPosition.X;
double dY = currentPosition.Y - lastPosition.Y;
this.lastPosition = currentPosition;
Transform oldTransform = attachedElement.RenderTransform;
TransformGroup rt = new TransformGroup();
TranslateTransform newPos = new TranslateTransform();
newPos.X = dX;
newPos.Y = dY;
translatePosition = newPos;
if (oldTransform != null)
{
rt.Children.Add(oldTransform);
}
rt.Children.Add(newPos);
MatrixTransform mt = new MatrixTransform();
mt.Matrix = rt.Value;
attachedElement.RenderTransform = mt;
}
}
void MouseIsUp(object sender, MouseButtonEventArgs e)
{
isDragging = false;
attachedElement.ReleaseMouseCapture();
}
void MouseIsDown(object sender, MouseButtonEventArgs e)
{
isDragging = true;
lastPosition = e.GetPosition(parent);
attachedElement.CaptureMouse();
}
}
{
private bool isDragging = false;
private UIElement attachedElement;
private UserControl parent;
Point lastPosition;
TranslateTransform translatePosition;
protected override void OnAttached()
{
attachedElement = this.AssociatedObject;
parent = Application.Current.RootVisual as UserControl;
attachedElement.MouseLeftButtonDown += new MouseButtonEventHandler(MouseIsDown);
attachedElement.MouseLeftButtonUp += new MouseButtonEventHandler(MouseIsUp);
attachedElement.MouseMove += new MouseEventHandler(MouseIsMoving);
}
void MouseIsMoving(object sender, MouseEventArgs e)
{
if (isDragging)
{
Point currentPosition = e.GetPosition(parent);
double dX = currentPosition.X - lastPosition.X;
double dY = currentPosition.Y - lastPosition.Y;
this.lastPosition = currentPosition;
Transform oldTransform = attachedElement.RenderTransform;
TransformGroup rt = new TransformGroup();
TranslateTransform newPos = new TranslateTransform();
newPos.X = dX;
newPos.Y = dY;
translatePosition = newPos;
if (oldTransform != null)
{
rt.Children.Add(oldTransform);
}
rt.Children.Add(newPos);
MatrixTransform mt = new MatrixTransform();
mt.Matrix = rt.Value;
attachedElement.RenderTransform = mt;
}
}
void MouseIsUp(object sender, MouseButtonEventArgs e)
{
isDragging = false;
attachedElement.ReleaseMouseCapture();
}
void MouseIsDown(object sender, MouseButtonEventArgs e)
{
isDragging = true;
lastPosition = e.GetPosition(parent);
attachedElement.CaptureMouse();
}
}
참고로 위 코드는 Sample Silverlight 3 Behaviors 에서 다운 받은 자료 중 하나로 UIElement를 Drag 가능하도록 하는 Behavior입니다.
Behavior class 를 정의 한 뒤 Expression Blend 3 Preview에서 솔루션을 Open하면, Asset Library의 Behaviors에 추가 되신 것을 확인 할 수 있습니다.
작성하신 DragBehavior를 Drag가 가능하게 하기 위한 DependencyObject에 Drag하여 추가하시면 비하인드 코드 상에서 아무런 조작을 하지 않아도, DragBehavior가 Add 된 DependencyObject는 실행시 Drag가 가능하게 됩니다.
2. FrameworkElement의 Event에 대한 Trigger 구현
Microsoft.Expression.Interativity.TargetedTriggerAction<FrameworkElement> 를 상속받아 대상이 되는 FrameworkElement의 Event에 대한 Trigger를 구현하는 Behavior class를 정의 할 수 있습니다.
public class PopupBehavior : Microsoft.Expression.Interactivity.TargetedTriggerAction<FrameworkElement>
{
protected override void Invoke(object parameter)
{
MessageBox.Show("Popup!");
}
}
{
protected override void Invoke(object parameter)
{
MessageBox.Show("Popup!");
}
}
위 코드는 FrameworkElement의 Event에 대하여 MessageBox를 띄워주게 될 것입니다.
이렇게 구현 된 클래스를 빌드 한 뒤, Microsoft Expression Blend 3 Preview에서 솔루션을 Open하면 Asset Library의 Behaviors 에 추가 되 있습니다. PopupBehavior를 Button에 연결 해 보겠습니다.
TargetedTriggerAction Behavior는 Target이 되는 FrameworkElemet에 연결 시, Properties에 Trigger 속성을 설정하는 부분이 나옵니다. 여기서 EventName을 정하면, 해당하는 Event의 Trigger로 TargetedTriggerAction Behavior가 동작하게 됩니다. 정확히는 override 된 TargetedTriggerAction.Invoke(object parameter) 함수가 실행 되는 것입니다.
또, Property를 추가하여 사용자 원하는 Message를 입력받아 출력할 수 있도록 할 수 있습니다.
public class PopupBehavior : Microsoft.Expression.Interactivity.TargetedTriggerAction<FrameworkElement>
{
[Category("Message Box Properties")]
public string PopupText
{
get { return (string)GetValue(PopupTextProperty); }
set { SetValue(PopupTextProperty, value); }
}
public static readonly DependencyProperty PopupTextProperty = DependencyProperty.Register("Popup Text", typeof(string), typeof(PopupBehavior), new PropertyMetadata("Input Popup Text!"));
protected override void Invoke(object parameter)
{
MessageBox.Show(PopupText);
}
}
{
[Category("Message Box Properties")]
public string PopupText
{
get { return (string)GetValue(PopupTextProperty); }
set { SetValue(PopupTextProperty, value); }
}
public static readonly DependencyProperty PopupTextProperty = DependencyProperty.Register("Popup Text", typeof(string), typeof(PopupBehavior), new PropertyMetadata("Input Popup Text!"));
protected override void Invoke(object parameter)
{
MessageBox.Show(PopupText);
}
}
[Category("카테고리명")] 으로 Property에 대한 Category를 지정하게 되면, Microsoft Expression Blend 3 Preivew 상에서 다음 그림에서 처럼 표시 됩니다.
이렇게 되면, 사용자가 직접 입력한 PopupText가 Button의 Cilck Event 시 실행되게 됩니다.