안녕하세요, Workflow Foundation (WF)의 신비로운 세계를 탐험하는 여러분!
오늘 다룰 주제는 ExpressionTextBox와 ModelItem의 바인딩 관계입니다.
무슨 소린지 모르겠다고요? 그럼 이 포스트를 통해 이 둘의 관계가 얼마나 중요하고 흥미로운지 알게 될 겁니다.
일단 커피 한잔을 준비하고 앉으세요. 시작해 봅시다!
ExpressionTextBox는 Windows Workflow Foundation에서 제공하는 특별한 텍스트 박스 컨트롤입니다.
“그래서 특별한 게 뭐야?” 라고 물으신다면, 이 텍스트 박스는 단순한 문자열을 넘어 표현식(expression)을 입력받을 수 있다는 점입니다.
예를 들어, "Hello, " + Name 같은 VB 표현식을 그대로 입력받아, 런타임에서 그 값을 처리할 수 있습니다.
ModelItem은 디자인 타임에 워크플로우 모델을 표현하는 객체입니다.
이 객체는 액티비티나 속성, 그리고 메타데이터를 포함하며, 디자이너에서 이들을 어떻게 표현할지를 관리합니다.
단순히 말해서, ExpressionTextBox와 ModelItem의 바인딩은 디자이너의 UI와 액티비티 코드 사이의 다리 역할을 합니다.
예를 들어, Assign 액티비티의 To 속성에 어떤 값이 설정되어 있는지 바로 확인하고 싶다면, 이를 위한 UI 요소로 ExpressionTextBox를 사용하면 됩니다.
아래에 간단한 예를 준비했습니다.
이 예에서는 Assign 액티비티의 디자이너를 사용할 건데, 이 액티비티는 변수에 값을 할당하는 기본적인 워크플로우 액티비티입니다.
<sap:ActivityDesigner x:Class="CustomActivities.AssignDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation">
<StackPanel>
<TextBlock Text="Assign To:" />
<sapv:ExpressionTextBox Expression="{Binding Path=ModelItem.To, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=Out }"
UseLocationExpression="True" OwnerActivity="{Binding Path=ModelItem}" />
</StackPanel>
</sap:ActivityDesigner>
public partial class AssignDesigner
{
public AssignDesigner()
{
InitializeComponent();
}
}
이렇게 하면 Assign 액티비티의 To 속성이 ExpressionTextBox와 바인딩됩니다. 이제 이 TextBox에 표현식을 입력하면, 그 값이 실제 워크플로우 모델의 To 속성에 반영되죠.
using System;
using System.Activities;
namespace CustomActivities
{
[Designer(typeof(AssignDesigner))] // AssignDesigner를 지정
public sealed class AssignActivity : CodeActivity
{
// To 속성: 변수에 할당될 값 혹은 표현식
public InArgument<string> To { get; set; }
// CodeActivity 클래스에서 Execute 메서드를 오버라이드해야 함
protected override void Execute(CodeActivityContext context)
{
// To 속성에서 실제 값을 가져옴
string toValue = context.GetValue(this.To);
// 실제 작업 로직 (여기서는 단순히 콘솔에 출력)
Console.WriteLine($"Assigning value: {toValue}");
}
}
}
AssignActivity에 어트리뷰트를 추가하여 디자이너를 명시적으로 지정할 수도 있습니다.
이제 AssignActivity 액티비티를 워크플로우 디자이너에 드래그 앤 드롭할 때 AssignDesigner가 사용되며, To 속성은 디자이너의 ExpressionTextBox와 바인딩 될 것입니다.
바인딩은 세 가지 주요 속성을 통해 이루어집니다:
OwnerActivity: 이 속성은 ExpressionTextBox가 어떤 ModelItem, 즉 어떤 액티비티에 속해 있는지를 나타냅니다. 즉, 표현식의 주인공은 누구인가요?
Converter: ArgumentToExpressionConverter 같은 데이터 변환기를 이용해서, ModelItem의 속성 값을 ExpressionTextBox가 이해할 수 있는 형식으로 변환해 줍니다.
ConverterParameter: “In”, “Out” 같은 추가 정보를 전달해, 데이터 변환기가 어떤 방식으로 변환을 진행할지 알려줍니다.
ModelItem은 Windows Workflow Foundation (WF)의 디자인 타임에 액티비티의 모델을 나타내는 객체입니다.
그러므로, 액티비티 디자이너 (예: AssignDesigner)가 로드될 때, 해당 액티비티 (예: AssignActivity)를 대표하는 ModelItem 인스턴스가 자동으로 생성됩니다.
일반적으로 ModelItem은 디자이너의 DataContext에 자동으로 설정됩니다.
이는 WPF (Windows Presentation Foundation)의 데이터 바인딩 메커니즘을 사용하여 이루어집니다.
따라서, ExpressionTextBox의 OwnerActivity 속성에 {Binding Path=ModelItem}과 같은 바인딩 표현식을 사용하면, ModelItem은 자동으로 해당 액티비티 (AssignActivity 등)와 연결됩니다.
디버깅: 디자이너 코드에서 디버깅을 통해 ModelItem의 속성과 값들을 확인할 수 있습니다.
코드에서 명시적으로 액세스: 디자이너의 코드 뒷면 (Code-behind)에서 this.ModelItem 또는 다른 메커니즘을 통해 ModelItem에 액세스할 수 있습니다. 이를 통해 어떤 액티비티 모델이 연결되어 있는지 확인할 수 있습니다.
DataContext 확인: WPF 디자이너에는 데이터 컨텍스트가 자주 사용되므로, 이를 통해 현재 ModelItem이 무엇인지 확인할 수 있습니다.
이벤트 로깅: 액티비티 디자이너가 로드될 때 이벤트를 로깅하도록 코드를 작성하여, 어떤 ModelItem이 생성되는지 로그를 통해 확인할 수 있습니다.
리플렉션: 더 복잡한 경우에는 .NET의 리플렉션을 사용하여 런타임에 ModelItem 객체를 조사할 수도 있습니다.
디자이너 내 UI 요소: 디자이너 내에 현재 연결된 ModelItem 정보를 표시하는 UI 요소를 추가할 수도 있습니다.
이러한 방법들을 통해 ModelItem과 AssignActivity가 제대로 연결되었는지 확인할 수 있습니다.
이렇게 해서 ExpressionTextBox와 ModelItem의 신비로운 바인딩에 대한 여행을 마치게 되었습니다.
어떤가요, 꽤 흥미로우시죠? 이 두 요소 사이의 마법 같은 바인딩을 이해하고 나면, 여러분의 워크플로우 애플리케이션은 훨씬 더 강력해질 것입니다.