MaskedTextBox 를 레거시와 동일하게 프롬프트 문자로 표시

4단계 육안 대조에서 발견한 차이. 마스크 패턴을 그대로 그려서 값이 이미 입력된 것처럼 보였다.

    레거시    ___년 __월 __일   (프롬프트 문자)
    SheetMe   0000년 90월 90일  (마스크 패턴 원문)

저장 데이터와는 무관한 표시 문제지만, 운영 실사용이 MaskedTextBox 475개 / Mask 보유 460개라
자주 눈에 띈다.

LegacyMask.ToPromptDisplay 신설(Core, 순수 함수) — 입력 자리 지시자는 프롬프트 문자로,
리터럴은 그대로, 이스케이프(\)는 다음 문자를 리터럴로, 대소문자 변환자(< > |)는 표시하지 않는다.
활성 디자인 전수 census 로 지원 범위를 정했다: 등장 지시자는 0(2,675) 9(687) #(12) 와
이스케이프 \(2) 뿐이고 문자류(L ? & C A a)와 변환자는 쓰이지 않는다. PromptChar 속성을 가진
컨트롤은 0개라 전부 기본값 '_' 이지만, 속성이 있으면 반영하도록 구현했다.

구분자 . , : / $ 는 WinForms 가 문화권 구분자로 치환하지만 원문 그대로 둔다 —
운영 마스크는 보이는 대로 쓰이고 레거시 화면도 그렇게 나온다.

MaskDisplay 는 표시 전용 파생 속성이라 PropBag 에 아무것도 쓰지 않는다(왕복 무손실 유지).
인스펙터 편집용 Mask 원문 속성은 그대로 둔다.

검증: 테스트 98/98(마스크 28건 추가 — 운영 실사용 마스크 10종, 이스케이프, 문자류 지시자,
변환자, PromptChar 지정, 끝 백슬래시, 표시 길이 보존). S481 재렌더로 레거시와 동일 표시 확인.
edit-smoke 실패 0, 왕복 1,271건 diff 0/예외 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Msystech
2026-08-12 09:20:30 +09:00
co-authored by Claude Fable 5
parent d1e488625e
commit a749e18e7b
4 changed files with 183 additions and 2 deletions
@@ -28,9 +28,17 @@ public sealed class TextBoxViewModel : ControlViewModel
/// <summary>마스크 입력 (레거시 MaskedTextBox)</summary>
public sealed class MaskedTextBoxViewModel : ControlViewModel
{
/// <summary>입력 마스크</summary>
/// <summary>입력 마스크 원문 — 인스펙터 편집용</summary>
public string Mask => Prop("Mask") ?? string.Empty;
/// <summary>
/// 빈 값일 때 캔버스에 그릴 문자열 — 레거시와 동일하게 입력 자리를 프롬프트 문자로 표시한다
/// (예: <c>0000년 90월 90일</c> → <c>____년 __월 __일</c>).
/// 마스크 원문을 그대로 그리면 값이 입력된 것으로 오해하게 된다.
/// </summary>
public string MaskDisplay => LegacyMask.ToPromptDisplay(
Mask, (Prop("PromptChar") is { Length: > 0 } p) ? p[0] : LegacyMask.DefaultPromptChar);
public MaskedTextBoxViewModel(ControlElement model) : base(model) { }
}