별도 창 전수 점검 — 암시 Window 스타일이 파생 클래스에 적용된 적이 없었다

사용자 지적: "다른 창으로(새창으로 열리는) 실행하는 항목들도 모두 점검해줘".

[근본 원인 — 대화상자 전체가 다크에서 흰 창이었다]
WPF 는 암시 스타일을 요소의 **정확한 런타임 타입**으로만 찾는다. 저장소의 모든 창이
Window 를 상속한 클래스(SheetOpenDialogView : Window, QueryEditorWindow : Window …)라
DesignerTheme.xaml 의 <Style TargetType="Window"> 는 **단 한 번도 적용된 적이 없다**.
결과: 창 배경이 WPF 기본 흰색으로 남고, 그 위 글자는 암시 TextBlock 스타일(B.Ink #EDEDED)을
정상적으로 받는다 → **다크 테마에서 흰 바탕에 흰 글자**. 쿼리 편집기의 변수 목록처럼 라벨이
통째로 사라지는 화면이 나왔다.

라이트에서 눈에 덜 띈 이유는 우연이다 — 기본 흰색(#FFFFFF)이 의도값 B.AppBg(#F5F5F5)와
거의 같아서다. 그래서 지금까지 라이트만 보고는 발견되지 않았다.

수정: 스타일에 x:Key="ThemedWindow" 를 주고 창 10종에 직접 걸었다(코드로 짓는
ColorPickerWindow 는 생성자에서 TryFindResource). 순수 Window 인스턴스용 암시 스타일은
BasedOn 으로 남겼다. 앞으로 창을 추가할 때 잊지 않도록 스타일 위에 경고 주석을 붙였다.

[신규 진단 --dialog-shots <출력폴더>]
이 결함은 정적 분석으로는 못 잡았다(앞선 감사에서 "대화상자들은 암시 Window 스타일을 그대로
받는다"고 잘못 결론냈다). 실입력 주입은 화면 잠금·세션 격리 상태에서 OS 가 거부한다
(SetCursorPos 무시, SendKeys "Access is denied" — 이번에도 중간부터 막혔다).
그래서 창을 화면 밖(-10000)에 띄워 RenderTargetBitmap 으로 찍는 진단을 만들었다.
창 8종 × 2테마 = 16장을 한 번에 남기고, 각 창의 **해석된 Background 와 Style 적용 여부를
텍스트로 함께 보고**한다 — 픽셀만 보면 원인을 못 가린다(실제로 이 한 줄이 원인을 확정했다).
표본 데이터는 실제 사용 시와 같은 형태로 넣었다(빈 껍데기를 찍으면 의미가 없다).

함정 2개를 코드에 남겼다.
· 기본 ShutdownMode 가 OnLastWindowClose 라 찍고 닫는 순간 앱이 종료된다 → OnExplicitShutdown.
· Window.Content 만 렌더하면 창 배경이 빠져 투명(=PNG 검정)이 되고, 다크처럼 보이는 착시로
  라이트 결함이 가려진다 → 배경을 먼저 칠하고 그 위에 콘텐츠를 그린다.

[함께 고친 것 — 여러 줄 입력이 세로 가운데 정렬]
쿼리 편집기의 SQL 이 큰 상자 한가운데 떠 있었다. 템플릿 트리거가 ScrollViewer 의
VerticalContentAlignment 만 Stretch 로 바꿨는데, 텍스트를 배치하는 건 TextBox 자신의
VerticalContentAlignment 이라 아무 효과가 없었다. Style.Triggers 로 옮겨 Top 으로 두고
여러 줄일 때 Padding 도 넉넉히 준다. 인스펙터의 여러 줄 속성 행에도 함께 적용된다.

검증: 창 8종 × 2테마 전부 재렌더해 배경 확인(다크 #0E0E0E / 라이트 #F5F5F5,
미리보기만 의도대로 B.CanvasBg). 테스트 124/124, edit-smoke 실패 0,
**종이 렌더 P062 픽셀 대조 차이 0**.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Msystech
2026-08-12 12:54:55 +09:00
co-authored by Claude Opus 5
parent ff87353d0d
commit 308197c15e
14 changed files with 245 additions and 14 deletions
+5
View File
@@ -171,6 +171,11 @@ public partial class App : Application
return Diagnostics.DbSmoke.RunTableSearch(args[1], args[2]); return Diagnostics.DbSmoke.RunTableSearch(args[1], args[2]);
} }
if (args.Length >= 2 && args[0] == "--dialog-shots")
{
return Diagnostics.DialogShots.Run(args[1]);
}
MessageBox.Show($"알 수 없는 진단 옵션입니다: {args[0]}", "서식생성기", MessageBox.Show($"알 수 없는 진단 옵션입니다: {args[0]}", "서식생성기",
MessageBoxButton.OK, MessageBoxImage.Warning); MessageBoxButton.OK, MessageBoxImage.Warning);
return 2; return 2;
@@ -0,0 +1,189 @@
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using SheetMe.Core.Models;
using SheetMe.Data.Stores;
using SheetMe.Designer.Services;
using SheetMe.Designer.ViewModels;
namespace SheetMe.Designer.Diagnostics;
/// <summary>
/// 별도 창(대화상자) 오프스크린 스냅샷 — <c>--dialog-shots &lt;출력폴더&gt;</c>.
///
/// 창 10종을 다크·라이트 양 테마로 열어 PNG 로 남긴다. 목적은 하나다:
/// <b>테마 대비 결함을 사람 손 없이 재현 가능하게 확인한다.</b>
/// 실입력(마우스·키보드) 주입은 화면 잠금·세션 격리 상태에서 OS 가 거부하지만
/// 이 경로는 창을 화면 밖에 띄워 RenderTargetBitmap 으로 찍으므로 그 제약을 받지 않는다.
///
/// 창은 화면 밖(-10000)에 <c>Show()</c> 로 띄운다 — 레이아웃이 실제로 돌아야 템플릿·트리거가
/// 적용된 상태로 찍힌다(Measure/Arrange 만으로는 Window 크롬이 구성되지 않는다).
/// 모든 창은 찍은 뒤 즉시 닫는다.
/// </summary>
public static class DialogShots
{
#region Methods
public static int Run(string outputDirectory)
{
try
{
Directory.CreateDirectory(outputDirectory);
// 기본 ShutdownMode 는 OnLastWindowClose 라, 찍고 닫는 순간 마지막 창이 사라져 앱이 종료된다
// (그 뒤 Application.Current 가 null 이 되어 테마 교체에서 NRE). 명시 종료로 바꾼다.
Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
var lines = new List<string>();
foreach (var light in new[] { false, true })
{
ThemeManager.Apply(light);
var suffix = light ? "light" : "dark";
foreach (var (name, factory) in Factories())
{
try
{
var window = factory();
Capture(window, Path.Combine(outputDirectory, $"{name}-{suffix}.png"));
// 창 배경이 실제로 무엇으로 해석됐는지 함께 남긴다 — 픽셀만 보면 원인을 못 가린다.
// WPF 는 암시 스타일을 요소의 '정확한 타입'으로만 찾으므로, Window 를 상속한
// 대화상자에는 <Style TargetType="Window"> 가 적용되지 않는다(기본 흰 배경이 된다).
var background = window.Background is SolidColorBrush solid
? solid.Color.ToString()
: window.Background?.ToString() ?? "(null)";
var styled = window.Style is not null ? "스타일적용" : "스타일없음";
lines.Add($"OK {name}-{suffix} 배경={background} {styled}");
}
catch (Exception ex)
{
lines.Add($"FAIL {name}-{suffix} — {ex.GetType().Name}: {ex.Message}");
}
}
}
File.WriteAllText(Path.Combine(outputDirectory, "_report.txt"),
string.Join(Environment.NewLine, lines));
Console.WriteLine(string.Join(Environment.NewLine, lines));
return lines.Any(l => l.StartsWith("FAIL", StringComparison.Ordinal)) ? 1 : 0;
}
catch (Exception ex)
{
Console.Error.WriteLine($"대화상자 스냅샷 실패: {ex}");
return 1;
}
}
/// <summary>창 생성기 목록 — 실제 사용 시와 같은 인자로 만든다(빈 껍데기를 찍으면 의미가 없다)</summary>
private static List<(string Name, Func<Window> Factory)> Factories()
{
var designer = SampleDesigner();
return new List<(string, Func<Window>)>
{
("01-sheet-open", () => new Views.SheetOpenDialogView(_ => SampleSheets())),
("02-sheet-history", () => new Views.SheetHistoryDialogView("S999", "표본 서식", SampleVersions())),
("03-query-editor", () => new Views.QueryEditorWindow("데이터소스",
"SELECT ChtNum, PatNam FROM P_PatMst\nWHERE ChtNum = <<M.CMM.HISOperatingInfo.bzPatientInfo.ChtNum>>")),
("04-tag-picker", () => new Views.TagPickerDialogView("동작 태그", SampleTags(), SampleTags()[1])),
("05-mask-picker", () => new Views.MaskPickerDialogView("0000년 90월 90일")),
("06-font-manager", () => new Views.FontManagerDialogView(designer)),
("07-register-sheet", () => new Views.RegisterSheetDialogView("S999", "표본 서식")),
("08-preview", () => new Views.PreviewWindow(designer)),
};
}
/// <summary>화면 밖에 띄워 레이아웃을 돌린 뒤 PNG 로 찍고 닫는다</summary>
private static void Capture(Window window, string pngPath)
{
window.WindowStartupLocation = WindowStartupLocation.Manual;
window.Left = -10000;
window.Top = -10000;
window.ShowInTaskbar = false;
window.Show();
window.UpdateLayout();
// 레이아웃·비동기 로딩(Loaded 핸들러)이 한 바퀴 돌게 한다
Pump();
// 창 자체를 렌더한다 — Content 만 찍으면 Window.Background(B.AppBg)가 빠져 투명이 되고,
// PNG 에서 검정으로 저장돼 "다크처럼 보이는" 착시가 생긴다(라이트 결함이 가려진다).
var content = (FrameworkElement)window.Content;
var width = (int)Math.Ceiling(content.ActualWidth > 0 ? content.ActualWidth : window.Width);
var height = (int)Math.Ceiling(content.ActualHeight > 0 ? content.ActualHeight : window.Height);
var bitmap = new RenderTargetBitmap(Math.Max(1, width), Math.Max(1, height), 96, 96, PixelFormats.Pbgra32);
var drawing = new DrawingVisual();
using (var context = drawing.RenderOpen())
{
context.DrawRectangle(window.Background ?? Brushes.Transparent, null, new Rect(0, 0, width, height));
context.DrawRectangle(new VisualBrush(content) { Stretch = Stretch.None, AlignmentX = AlignmentX.Left, AlignmentY = AlignmentY.Top },
null, new Rect(0, 0, width, height));
}
bitmap.Render(drawing);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
using (var stream = File.Create(pngPath))
{
encoder.Save(stream);
}
window.Close();
}
/// <summary>디스패처 큐를 비운다(Loaded/바인딩 갱신 반영)</summary>
private static void Pump()
{
for (var i = 0; i < 3; i++)
{
System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(
() => { }, System.Windows.Threading.DispatcherPriority.ContextIdle);
}
}
#endregion
#region Methods -
private static List<SheetSummary> SampleSheets() => new()
{
new SheetSummary("C020", "협진기록지", true, true, "A", "의사기록"),
new SheetSummary("C030", "Doctor's Order List", false, true, "A", "의사기록"),
new SheetSummary("P001", "간호 기록지", true, true, "E", "간호기록"),
new SheetSummary("F004", "임상생리신경검사", true, false, "D", "검사결과"),
new SheetSummary("Z001", "분류 없는 서식", false, true, string.Empty, "(미분류)"),
};
private static List<DesignVersionInfo> SampleVersions() => new()
{
new DesignVersionInfo(52443, "202608121030", "011825", false),
new DesignVersionInfo(52380, "202607161422", "011825", true),
new DesignVersionInfo(52241, "202607160901", "MSYS", true),
};
private static string[] SampleTags() => new[]
{
"SetPatientName", "SetChartNumber", "EnableControl", "SetVisitDate", "ClearValue",
};
/// <summary>폰트 관리자·미리보기용 표본 문서 — 컨트롤이 있어야 목록이 비지 않는다</summary>
private static DesignerViewModel SampleDesigner()
{
var document = new FormDocument { FormId = "S999", Title = "표본 서식" };
var page = Core.Serialization.LegacyXmlSerializer.CreateEmptyPage(1);
page.Controls.Add(NewControl("Label", "Label1", "환자명", 40, 40, 120, 24));
page.Controls.Add(NewControl("TextBox", "TextBox1", string.Empty, 170, 40, 200, 26));
page.Controls.Add(NewControl("Label", "Label2", "생년월일", 40, 80, 120, 24));
document.Pages.Add(page);
return new DesignerViewModel(document);
}
private static ControlElement NewControl(string type, string id, string text, double x, double y, double w, double h)
{
var element = new ControlElement { Type = type, Id = id };
element.Bounds.X = x;
element.Bounds.Y = y;
element.Bounds.W = w;
element.Bounds.H = h;
if (text.Length > 0)
{
element.Props.SetText("Text", text);
}
return element;
}
#endregion
}
+26 -4
View File
@@ -13,13 +13,26 @@
<!-- ===== 창 공통(다이얼로그 배경/폰트 — 로컬 지정이 있으면 로컬 우선) ===== <!-- ===== 창 공통(다이얼로그 배경/폰트 — 로컬 지정이 있으면 로컬 우선) =====
FontSize/Foreground 가 없으면 대화상자들이 WPF 기본 12px + 시스템 검정으로 렌더돼 FontSize/Foreground 가 없으면 대화상자들이 WPF 기본 12px + 시스템 검정으로 렌더돼
메인 셸(13px)과 결이 어긋난다. 토큰 참조는 DynamicResource 로 둬야 테마 전환에 따라간다. --> 메인 셸(13px)과 결이 어긋난다. 토큰 참조는 DynamicResource 로 둬야 테마 전환에 따라간다. -->
<Style TargetType="Window"> <!--
⚠ 창에는 **반드시 Style="{StaticResource ThemedWindow}" 를 직접 걸어야 한다.**
WPF 는 암시 스타일을 요소의 '정확한 런타임 타입'으로만 찾는다. 모든 대화상자가
Window 를 **상속한** 클래스(SheetOpenDialogView : Window 등)라 아래 암시 스타일은
이들에게 단 한 번도 적용된 적이 없었다 — 진단(dialog-shots)이 창 8종 전부
배경=#FFFFFFFF / Style=null 로 보고했다. 결과적으로 다크 테마에서 흰 창 위에
B.Ink(#EDEDED) 글자가 얹혀 대화상자 내용이 통째로 보이지 않았다.
(TextBlock·TextBox 등은 정확한 타입이라 암시 스타일이 정상 적용돼, 창 배경만
WPF 기본 흰색으로 남는 형태로 드러났다.)
-->
<Style x:Key="ThemedWindow" TargetType="Window">
<Setter Property="Background" Value="{DynamicResource B.AppBg}" /> <Setter Property="Background" Value="{DynamicResource B.AppBg}" />
<Setter Property="FontFamily" Value="Malgun Gothic" /> <Setter Property="FontFamily" Value="Malgun Gothic" />
<Setter Property="FontSize" Value="13" /> <Setter Property="FontSize" Value="13" />
<Setter Property="Foreground" Value="{DynamicResource B.Ink}" /> <Setter Property="Foreground" Value="{DynamicResource B.Ink}" />
</Style> </Style>
<!-- 순수 Window 인스턴스용(파생 클래스에는 위 키 스타일을 직접 걸어야 한다) -->
<Style TargetType="Window" BasedOn="{StaticResource ThemedWindow}" />
<!-- ===== 타이포 ===== --> <!-- ===== 타이포 ===== -->
<Style TargetType="TextBlock"> <Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{DynamicResource B.Ink}" /> <Setter Property="Foreground" Value="{DynamicResource B.Ink}" />
@@ -112,13 +125,22 @@
<Trigger Property="IsKeyboardFocused" Value="True"> <Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="bd" Property="BorderBrush" Value="{DynamicResource B.Accent}" /> <Setter TargetName="bd" Property="BorderBrush" Value="{DynamicResource B.Accent}" />
</Trigger> </Trigger>
<Trigger Property="AcceptsReturn" Value="True">
<Setter TargetName="PART_ContentHost" Property="VerticalContentAlignment" Value="Stretch" />
</Trigger>
</ControlTemplate.Triggers> </ControlTemplate.Triggers>
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Style.Triggers>
<!--
여러 줄 입력은 위에서부터 흘러야 한다. 종전에는 템플릿 트리거가 ScrollViewer 의
VerticalContentAlignment 만 Stretch 로 바꿨는데, 텍스트를 배치하는 것은 TextBox 자신의
VerticalContentAlignment 이라 아무 효과가 없었다 — 쿼리 편집기에서 SQL 이 큰 상자
한가운데 떠 있었다(dialog-shots 진단으로 확인).
-->
<Trigger Property="AcceptsReturn" Value="True">
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="Padding" Value="6,5" />
</Trigger>
</Style.Triggers>
</Style> </Style>
<!-- Framer 식 슬라이더(불투명도 등): 얇은 트랙 + 흰 원형 썸 --> <!-- Framer 식 슬라이더(불투명도 등): 얇은 트랙 + 흰 원형 썸 -->
@@ -54,6 +54,11 @@ public sealed class ColorPickerWindow : Window
private ColorPickerWindow(string? initialHex) private ColorPickerWindow(string? initialHex)
{ {
Title = "색상 선택"; Title = "색상 선택";
// 암시 Window 스타일은 파생 클래스에 적용되지 않는다 — 직접 걸지 않으면 다크에서 흰 창이 된다
if (Application.Current?.TryFindResource("ThemedWindow") is Style themed)
{
Style = themed;
}
Width = 300; Width = 300;
SizeToContent = SizeToContent.Height; SizeToContent = SizeToContent.Height;
WindowStartupLocation = WindowStartupLocation.CenterOwner; WindowStartupLocation = WindowStartupLocation.CenterOwner;
@@ -2,7 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="폰트 일괄 변경" Width="620" Height="560" MinWidth="520" MinHeight="420" Title="폰트 일괄 변경" Width="620" Height="560" MinWidth="520" MinHeight="420"
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"> WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
Style="{StaticResource ThemedWindow}">
<DockPanel Margin="12"> <DockPanel Margin="12">
<TextBlock DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}" TextWrapping="Wrap" Margin="0,0,0,8" <TextBlock DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}" TextWrapping="Wrap" Margin="0,0,0,8"
Text="문서 전체의 (타입·글꼴·크기) 조합입니다. 변경할 조합을 선택(다중 가능)하고 새 글꼴을 지정하세요."/> Text="문서 전체의 (타입·글꼴·크기) 조합입니다. 변경할 조합을 선택(다중 가능)하고 새 글꼴을 지정하세요."/>
+2 -1
View File
@@ -16,7 +16,8 @@
Width="1440" Height="920" MinWidth="940" MinHeight="640" Width="1440" Height="920" MinWidth="940" MinHeight="640"
WindowStyle="None" WindowStartupLocation="CenterScreen" WindowStyle="None" WindowStartupLocation="CenterScreen"
Background="{DynamicResource B.AppBg}" FontFamily="Malgun Gothic" FontSize="13" Background="{DynamicResource B.AppBg}" FontFamily="Malgun Gothic" FontSize="13"
Loaded="OnWindowLoaded" StateChanged="OnWindowStateChanged" Closing="OnWindowClosing"> Loaded="OnWindowLoaded" StateChanged="OnWindowStateChanged" Closing="OnWindowClosing"
Style="{StaticResource ThemedWindow}">
<!-- <!--
파일/앱 계열만 창 단위로 바인딩한다. 편집 계열(Ctrl+Z/C/V/X/D/A/G)은 CanvasKeyboardBehavior 가 파일/앱 계열만 창 단위로 바인딩한다. 편집 계열(Ctrl+Z/C/V/X/D/A/G)은 CanvasKeyboardBehavior 가
@@ -2,7 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="마스크 편집" Width="620" Height="620" Title="마스크 편집" Width="620" Height="620"
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"> WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
Style="{StaticResource ThemedWindow}">
<DockPanel Margin="12"> <DockPanel Margin="12">
<!-- <!--
백슬래시를 글리프로 보여주지 않는다 — 한글 글꼴에서 원화 기호(₩)로 렌더되어 오해를 부른다. 백슬래시를 글리프로 보여주지 않는다 — 한글 글꼴에서 원화 기호(₩)로 렌더되어 오해를 부른다.
@@ -2,7 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="미리보기" Width="900" Height="1000" Title="미리보기" Width="900" Height="1000"
WindowStartupLocation="CenterOwner" Background="{DynamicResource B.CanvasBg}"> WindowStartupLocation="CenterOwner" Background="{DynamicResource B.CanvasBg}"
Style="{StaticResource ThemedWindow}">
<DockPanel> <DockPanel>
<ToolBarTray DockPanel.Dock="Top"> <ToolBarTray DockPanel.Dock="Top">
<ToolBar> <ToolBar>
@@ -2,7 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="쿼리 편집" Width="960" Height="560" MinWidth="720" MinHeight="400" Title="쿼리 편집" Width="960" Height="560" MinWidth="720" MinHeight="400"
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"> WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
Style="{StaticResource ThemedWindow}">
<DockPanel Margin="12"> <DockPanel Margin="12">
<TextBlock x:Name="HintText" DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}" TextWrapping="Wrap" Margin="0,0,0,8" <TextBlock x:Name="HintText" DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}" TextWrapping="Wrap" Margin="0,0,0,8"
Text="작성 시점에 &lt;&lt;변수&gt;&gt; 가 실제 값으로 치환됩니다. 변수는 클래스 전체 이름을 포함해야 하므로 우측 목록을 더블클릭해 삽입하세요 — 임의로 줄여 쓰면 치환되지 않고 SQL 에 그대로 남아 오류가 납니다."/> Text="작성 시점에 &lt;&lt;변수&gt;&gt; 가 실제 값으로 치환됩니다. 변수는 클래스 전체 이름을 포함해야 하므로 우측 목록을 더블클릭해 삽입하세요 — 임의로 줄여 쓰면 치환되지 않고 SQL 에 그대로 남아 오류가 납니다."/>
@@ -2,7 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="상용구 관리" Width="560" Height="520" MinWidth="480" MinHeight="380" Title="상용구 관리" Width="560" Height="520" MinWidth="480" MinHeight="380"
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"> WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
Style="{StaticResource ThemedWindow}">
<DockPanel Margin="12"> <DockPanel Margin="12">
<TextBlock x:Name="HeaderText" DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}" <TextBlock x:Name="HeaderText" DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}"
TextWrapping="Wrap" Margin="0,0,0,8"/> TextWrapping="Wrap" Margin="0,0,0,8"/>
@@ -2,7 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="신규 서식 등록" Width="420" SizeToContent="Height" Title="신규 서식 등록" Width="420" SizeToContent="Height"
WindowStartupLocation="CenterOwner" ShowInTaskbar="False" ResizeMode="NoResize"> WindowStartupLocation="CenterOwner" ShowInTaskbar="False" ResizeMode="NoResize"
Style="{StaticResource ThemedWindow}">
<StackPanel Margin="16"> <StackPanel Margin="16">
<TextBlock Text="E_ShtMst 에 등록되지 않은 서식입니다. 신규 등록 후 저장합니다." <TextBlock Text="E_ShtMst 에 등록되지 않은 서식입니다. 신규 등록 후 저장합니다."
TextWrapping="Wrap" Foreground="{DynamicResource B.Muted}" Margin="0,0,0,12"/> TextWrapping="Wrap" Foreground="{DynamicResource B.Muted}" Margin="0,0,0,12"/>
@@ -2,7 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="서식 수정이력" Width="560" Height="520" MinWidth="480" MinHeight="380" Title="서식 수정이력" Width="560" Height="520" MinWidth="480" MinHeight="380"
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"> WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
Style="{StaticResource ThemedWindow}">
<DockPanel Margin="12"> <DockPanel Margin="12">
<TextBlock x:Name="HeaderText" DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}" <TextBlock x:Name="HeaderText" DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}"
TextWrapping="Wrap" Margin="0,0,0,8"/> TextWrapping="Wrap" Margin="0,0,0,8"/>
@@ -2,7 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DB에서 서식 열기" Width="680" Height="560" Title="DB에서 서식 열기" Width="680" Height="560"
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"> WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
Style="{StaticResource ThemedWindow}">
<DockPanel Margin="12"> <DockPanel Margin="12">
<DockPanel DockPanel.Dock="Top"> <DockPanel DockPanel.Dock="Top">
<Button DockPanel.Dock="Right" Content="검색" Padding="14,4" Margin="6,0,0,0" Click="OnSearch" IsDefault="True"/> <Button DockPanel.Dock="Right" Content="검색" Padding="14,4" Margin="6,0,0,0" Click="OnSearch" IsDefault="True"/>
@@ -2,7 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="태그 선택" Width="480" Height="560" Title="태그 선택" Width="480" Height="560"
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"> WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
Style="{StaticResource ThemedWindow}">
<DockPanel Margin="12"> <DockPanel Margin="12">
<TextBlock x:Name="TitleText" DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}" <TextBlock x:Name="TitleText" DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}"
TextWrapping="Wrap" Margin="0,0,0,8"/> TextWrapping="Wrap" Margin="0,0,0,8"/>