CommandBinding in .NET: 간단하게 이해하기

.NET에서 GUI 애플리케이션을 개발하면서, 사용자의 액션을 감지하고 적절한 로직을 수행하는 것은 중요한 부분입니다.
CommandBinding은 이러한 과정을 더 효율적이고 관리하기 쉽게 만들어주는 매커니즘 중 하나입니다.
이 글에서는 CommandBinding이 무엇인지, 왜 사용해야 하는지에 대해 알아보고 간단한 예제 코드도 살펴보겠습니다.


1. CommandBinding이란?

CommandBinding은 명령과 해당 명령을 처리할 로직을 연결해주는 역할을 합니다.
일반적으로 버튼 클릭이나 키보드 단축키 등의 사용자 액션을 하나의 명령으로 추상화하여, 이 명령을 실제로 처리하는 로직과 연결시키는 방법입니다.



2. 왜 사용하는가?

코드의 재사용성

하나의 명령을 여러 UI 요소에 쉽게 바인딩할 수 있습니다. 예를 들어, “저장” 명령을 툴바 버튼과 메뉴 아이템에 동시에 연결할 수 있습니다.


느슨한 결합 (Loose Coupling)

UI 컨트롤과 실제 비즈니스 로직을 분리함으로써, 더 유지보수하기 좋은 코드를 작성할 수 있습니다.


테스트 용이성

명령 로직을 분리함으로써, 단위 테스트가 더 쉬워집니다.



3. 예제 코드

이 코드에서 ApplicationCommands.New 명령은 “새 문서를 생성합니다.”라는 메시지 박스를 띄우는 NewCommand_Executed 메서드에 바인딩됩니다.
NewCommand_CanExecute는 이 명령이 실행 가능한 상태인지를 판단합니다.


using System;
using System.Windows;
using System.Windows.Input;

namespace CommandBindingExample
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            // CommandBinding 객체 생성
            CommandBinding commandBinding = new CommandBinding();
            // Command에 ApplicationCommands.New 연결
            commandBinding.Command = ApplicationCommands.New;
            // 이 명령이 실행될 때 호출될 이벤트 핸들러 지정
            commandBinding.Executed += NewCommand_Executed;
            // 명령을 실행할 수 있는지 판단하는 이벤트 핸들러 지정
            commandBinding.CanExecute += NewCommand_CanExecute;
            // Window에 CommandBinding 추가
            this.CommandBindings.Add(commandBinding);
        }

        private void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("새 문서를 생성합니다.");
        }

        private void NewCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            // 여기서는 예시로 항상 true를 반환. 실제로는 조건을 확인해야 함.
            e.CanExecute = true;
        }
    }
}


추가 예시 1: “저장” 명령을 여러 곳에서 사용하기

“저장” 기능을 여러 곳에서 사용하고 싶다면, “저장” 버튼과 메뉴 아이템, 그리고 단축키 (Ctrl+S) 등에 같은 “저장” 명령을 연결할 수 있습니다.

private void SaveCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
    // 저장 로직
}


추가 예시 2: “복사/잘라내기/붙여넣기” 기능 구현

복사, 잘라내기, 붙여넣기와 같은 명령들도 여러 곳에서 재사용됩니다.
텍스트 박스뿐만 아니라, 그리드나 리스트 등에서도 사용될 수 있습니다.

private void CopyCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
    // 복사 로직
}

private void CutCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
    // 잘라내기 로직
}

private void PasteCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
    // 붙여넣기 로직
}


추가 예시 3: 사용자의 입력 유효성 검사

CanExecute 이벤트를 활용하면 명령을 실행할 수 있는 상태인지 미리 검사할 수 있습니다.
예를 들어, “삭제” 버튼이 있고 선택된 항목이 없을 때는 버튼을 비활성화하려면 다음과 같이 할 수 있습니다.

private void DeleteCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = selectedItem != null;
}

private void DeleteCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
    // 삭제 로직
}



4. 마치며

CommandBinding은 .NET 애플리케이션 개발에서 사용자 인터페이스와 로직을 효과적으로 연결하는 강력한 도구입니다.
코드의 재사용성을 높이고, 유지보수를 쉽게 만들어 줍니다.






정규표현식으로 시간 절약하기
당신의 하루에 몇 시간을 더하세요
WPF MVVM 패턴, 그리고 Binding
WPF(Windows Presentation Foundation) 시리즈
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을 확인해보자