Workflow 디자이너와 액티비티의 관계

안녕하세요, 여러분!

오늘은 그 누구도 쉽게 설명하지 않는, 워크플로우 디자이너와 액티비티가 어떻게 서로를 알아보는지에 대해 이야기하려고 합니다.

왜 이게 중요하냐고요? 워크플로우의 세계에서 디자이너와 액티비티의 관계는 마법과도 같은 존재입니다.

이것만 잘 이해해도, 워크플로우를 조종하는 마법사가 될 수 있습니다!

자, 그럼 시작해보죠!



1. 액티비티와 디자이너, 어떻게 만나는가?

일단 기본적으로 액티비티와 디자이너는 일대일 매핑으로 만나곤 합니다.

간단한 예를 들어 볼까요?


[Designer(typeof(MyActivityDesigner))]
public class MyActivity : Activity
{
    // ...
}

아주 간단하죠? MyActivity라는 액티비티가 있고, 이것은 MyActivityDesigner 디자이너와 매핑되어 있습니다.



2. 디자이너와 액티비티가 서로 어떻게 소통하는가?

사실 이 부분이 중요한데요, 디자이너가 로딩되는 순간은 워크플로우에 액티비티가 추가되는 그 순간입니다.

이때 ModelItem이라는 아이템이 디자이너와 액티비티를 이어주는 역할을 합니다.


ModelItem은 무엇인가요?

ModelItem은 현재 디자이너에 연결된 액티비티의 정보를 담고 있습니다.

디자이너 내에서 이 ModelItem을 사용하면 현재 바인딩된 액티비티에 액세스할 수 있습니다. 이게 어떻게 쓰이냐고요?

예를 들면 다음과 같습니다:

private void ActivityDesigner_Loaded(object sender, RoutedEventArgs e)
{
    if (ModelItem.ItemType == typeof(LogActivity))
    {
        // UI를 LogActivity에 맞게 변경
    }
    else if (ModelItem.ItemType == typeof(ErrorLogActivity))
    {
        // UI를 ErrorLogActivity에 맞게 변경
    }
}



3. 일대일 매핑과 다대일 매핑

일대일 매핑 (One-to-One Mapping)

일대일 매핑이란, 하나의 액티비티가 하나의 디자이너와 연결되는 것을 의미합니다.

이는 아주 간단하고 직관적인 방법입니다.

예를 들어, 내가 만든 MyActivity라는 액티비티가 있다고 해보겠습니다.

이 액티비티에 디자이너를 적용하려면 아래와 같이 코드를 작성하면 됩니다.


[Designer(typeof(MyActivityDesigner))]
public class MyActivity : Activity
{
    // ...
}

이렇게 하면 MyActivity 액티비티는 MyActivityDesigner 디자이너와 연결됩니다. 간단하죠?


다대일 매핑 (Many-to-One Mapping)

다대일 매핑은 하나의 디자이너가 여러 액티비티에 적용되는 경우를 의미합니다.

예를 들어, LogActivityErrorLogActivity라는 두 액티비티가 있고 이 두 액티비티가 같은 UI를 공유한다고 가정해보겠습니다.


LogActivity와 ErrorLogActivity 클래스

using System;
using System.Activities;

namespace CustomActivities
{
    public class LogActivity : CodeActivity
    {
        public InArgument<string> Message { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
            string message = context.GetValue(this.Message);
            Console.WriteLine($"Log: {message}");
        }
    }

    public class ErrorLogActivity : CodeActivity
    {
        public InArgument<string> ErrorMessage { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
            string message = context.GetValue(this.ErrorMessage);
            Console.WriteLine($"Error: {message}");
        }
    }
}


공통 디자이너 클래스

이 디자이너는 LogActivityErrorLogActivity 둘 다에 사용됩니다.

using System.Windows;
using System.Activities.Presentation.Metadata;
using System.Activities.Presentation;

namespace CustomActivities
{
    public partial class CommonLogDesigner
    {
        public CommonLogDesigner()
        {
            InitializeComponent();
        }
    }
}


디자이너 로드 이벤트 핸들러

디자이너가 로딩될 때 ModelItem을 체크하여 UI를 동적으로 업데이트하도록 설정합니다.

private void ActivityDesigner_Loaded(object sender, RoutedEventArgs e)
{
    if (ModelItem.ItemType == typeof(LogActivity))
    {
        // Update UI for LogActivity
    }
    else if (ModelItem.ItemType == typeof(ErrorLogActivity))
    {
        // Update UI for ErrorLogActivity
    }
}



4. 액티비티, 디자이너, ModelItem 관계를 정리해줘!

디자이너가 로딩되는 시점은 일반적으로 워크플로우 디자이너에 액티비티를 드래그 앤 드롭하여 추가했을 때나, 프로그래밍 방식으로 액티비티를 워크플로우에 추가했을 때입니다.

ModelItem은 이러한 시점에서 현재의 액티비티 인스턴스에 바인딩됩니다.

따라서 디자이너의 로직 내에서 ModelItem을 사용하면 현재 디자이너에 바인딩된 액티비티의 속성이나 메서드에 액세스할 수 있습니다.

이것은 디자이너가 액티비티의 상태를 렌더링하거나 수정하는 데 매우 유용합니다.

예를 들어, 위에서 보여준 다대일 매핑 예시에서의 ActivityDesigner_Loaded 메서드에서 ModelItem.ItemType을 체크하면, 현재 디자이너에 어떤 타입의 액티비티가 바인딩되어 있는지 알 수 있습니다.

이 정보를 바탕으로 디자이너의 UI를 동적으로 업데이트할 수 있습니다.



5. 마무리

디자이너와 액티비티, 그리고 그들을 연결하는 미스터리한 ModelItem이 이번 블로그의 핵심입니다.

이 세 가지만 잘 이해했다면, 여러분도 이제 워크플로우의 마법사입니다!






정규표현식의 유용한 패턴
#집합찾기 #반복찾기 #역참조 #조건달기
A 액티비티에서 B 액티비티로 데이터 전달하기
#WorkflowFoundation #InArgument #OutArugment #Variables
Microsoft UI Automation Framework 이해하기
#AutomationElement #TreeWalker #ControlPatterns
AppDomain 탐구
#AppDomain #격리 #어셈블리별도실행 #플러그인시스템
Chrome Extension 활용하여여 웹 페이지 XPath 정보 가져오기
#ChromeExtension #크롬확장프로그램 #XPath
Workflow 디자이너와 액티비티의 관계
#WorkflowFoundation #Designer #Activity #ModelItem
ExpressionTextBox와 ModelItem의 바인딩 관계
#WorkflowFoundation #ExpressionTextBox #ModelItem #Binding
Windows 레지스트리 간단 정리
#Windows #Registry #레지스트리
WPF MVVM 패턴, 그리고 Binding
#WPF #MVVM #Binding #Modle #View #ViewModel
오라클 SQL 성능 최적화 - 바인드 변수와 Shared Memory 이해하기
#Oracle #바인드변수 #SharedMemory #LibraryCache #SqlPlan
ActivityDesigner와 CodeActivity 이해하기
#WorkflowFoundation #ActivityDesigner #CodeActivity
Selenium Implicit vs Explicit - 웹 요소 기다리기
#Selenium #IWebDriver #Implicit #Explicit
.NET에서 Selenium 활용하기 - 3가지 실전 예제
#Selenium #ChromeDriver #FindElements
.NET에서 CommandBinding 활용하기
#.NET #CommandBinding #디자인패턴
워크플로우 파운데이션(Workflow Foundation) 소개
#WorkflowFoundation #소개 #기본개념
AWS SAA 준비 - (4) 비용에 최적화된 아키텍처 설계
(정리) Exam Readiness - AWS Solutions Architect Associate
AWS SAA 준비 - (3) 안전한 아키텍처
(정리) Exam Readiness - AWS Solutions Architect Associate
AWS SAA 준비 - (2) 성능이 뛰어난 아키텍처 설계
(정리) Exam Readiness - AWS Solutions Architect Associate
AWS SAA 준비 - (1) 복원력을 갖춘 아키텍처 설계
(정리) Exam Readiness - AWS Solutions Architect Associate
15분 안에 ToC를 구현해보자!
Vanilla JS로 Table of Contents 구현하기
모듈
모던 자바스크립트 Deep Dive | 48장 | 모듈
에러 처리
모던 자바스크립트 Deep Dive | 47장 | 에러 처리
제너레이터와 async/await
모던 자바스크립트 Deep Dive | 46장 | 제너레이터와 async/await
프로미스
모던 자바스크립트 Deep Dive | 45장 | 프로미스
REST API
모던 자바스크립트 Deep Dive | 44장 | REST API
Ajax
모던 자바스크립트 Deep Dive | 43장 | Ajax
비동기 프로그래밍
모던 자바스크립트 Deep Dive | 42장 | 비동기 프로그래밍
타이머
모던 자바스크립트 Deep Dive | 41장 | 타이머
Set과 Map
모던 자바스크립트 Deep Dive | 37장 | Set과 Map
디스트럭처링
모던 자바스크립트 Deep Dive | 36장 | 디스트럭처링
브라우저의 렌더링 과정
모던 자바스크립트 Deep Dive | 38장 | 브라우저의 렌더링 과정
스프레드 문법
모던 자바스크립트 Deep Dive | 35장 | 스프레드 문법
이터러블
모던 자바스크립트 Deep Dive | 34장 | 이터러블
7번째 데이터 타입 Symbol
모던 자바스크립트 Deep Dive | 33장 | 7번째 데이터 타입 Symbol
String
모던 자바스크립트 Deep Dive | 32장 | String
RegExp
모던 자바스크립트 Deep Dive | 31장 | RegExp
Date
모던 자바스크립트 Deep Dive | 30장 | Date
Math
모던 자바스크립트 Deep Dive | 29장 | Math
DOM
모던 자바스크립트 Deep Dive | 39장 | DOM
Number
모던 자바스크립트 Deep Dive | 28장 | Number
배열
모던 자바스크립트 Deep Dive | 27장 | 배열
이벤트
모던 자바스크립트 Deep Dive | 40장 | 이벤트
ES6 함수의 추가 기능
모던 자바스크립트 Deep Dive | 26장 | ES6 함수의 추가 기능
클래스
모던 자바스크립트 Deep Dive | 25장 | 클래스
this
모던 자바스크립트 Deep Dive | 22장 | this
빌트인 객체
모던 자바스크립트 Deep Dive | 21장 | 빌트인 객체
strict mode
모던 자바스크립트 Deep Dive | 20장 | strict mode
클로저
모던 자바스크립트 Deep Dive | 24장 | 클로저
프로토타입
모던 자바스크립트 Deep Dive | 19장 | 프로토타입
함수와 일급 객체
모던 자바스크립트 Deep Dive | 18장 | 함수와 일급 객체
실행 컨텍스트
모던 자바스크립트 Deep Dive | 23장 | 실행 컨텍스트
생성자 함수에 의한 객체 생성
모던 자바스크립트 Deep Dive | 17장 | 생성자 함수에 의한 객체 생성
프로퍼티 어트리뷰트
모던 자바스크립트 Deep Dive | 16장 | 프로퍼티 어트리뷰트
let, const 키워드와 블록 레벨 스코프
모던 자바스크립트 Deep Dive | 15장 | let, const 키워드와 블록 레벨 스코프
전역 변수의 문제점
모던 자바스크립트 Deep Dive | 14장 | 전역 변수의 문제점
스코프
모던 자바스크립트 Deep Dive | 13장 | 스코프
함수
모던 자바스크립트 Deep Dive | 12장 | 함수
원시 값과 객체의 비교
모던 자바스크립트 Deep Dive | 11장 | 원시 값과 객체의 비교
객체 리터럴
모던 자바스크립트 Deep Dive | 10장 | 객체 리터럴
타입 변환과 단축 평가
모던 자바스크립트 Deep Dive | 9장 | 타입 변환과 단축 평가
제어문
모던 자바스크립트 Deep Dive | 8장 | 제어문
연산자
모던 자바스크립트 Deep Dive | 7장 | 연산자
데이터 타입
모던 자바스크립트 Deep Dive | 6장 | 데이터 타입
표현식과 문
모던 자바스크립트 Deep Dive | 5장 | 표현식과 문
변수
모던 자바스크립트 Deep Dive | 4장 | 변수
Iteration와 Generator
코드스피츠 77 ES6+ 3화 참조
WHATWG 탄생 배경
WHATWG, W3C, HTML의 관련에 대한 역사
프론트엔드(FE) 면접 질문 정리
FE관련 면접 질문 및 답변 정리한 내용입니다.
쿠버네티스(kubernetes, k8s) 용어 정리
쿠버네티스(kubernetes, k8s) 용어 정리
젠킨스(Jenkins) 정리
젠킨스(Jenkins) 정리
Docker 용어 정리
Docker 용어 정리
Git 용어 정리
Git 용어 정리
반응형 웹 디자인(Responsive Web Design)
CSS responsive 에 대하여
JS this에 대하여
this에 대해 알아보자
SQL*PLUS에 대하여
SQL*PLUS 정의 및 사용방법
Oracle에서 SQL Plan 확인하기
Oracle에서 SQL Plan을 확인해보자