'새 서식'을 없앤다 — 코드 없는 문서는 그린 뒤에 저장이 막힌다
서식은 항상 목록에서 골라 연다는 결정. ## 없앤 진입점 넷 - 파일 메뉴 '새 서식(N)' - Ctrl+N - 탭 흐름 옆 '+' 버튼(DesignerTheme.xaml) - 빈 화면의 '새 서식' 버튼 시작 시 빈 문서를 만들던 것도 없앴다. 그게 실제 이유다 — 코드 없는 문서는 DB 에 저장할 수 없고(FormId 가 "NewSheet"), 사용자는 한참 그려 넣은 뒤에야 그 사실을 알게 된다. 만들 수 있게 두는 것 자체가 함정이었다. 이제 기동 인자에 서식 코드가 없으면 아무것도 열지 않고 서식 목록 탭을 띄운다. 빈 화면 안내도 '서식 목록에서 열기' 하나로 줄였다(F4 · Ctrl+O 병기). CreateNew 와 파일 저장·열기 코드는 남긴다 — 접속 없이 도는 진단이 그 경로를 쓴다. UI 진입점만 없앤 것이고, 이는 'DB에서 열기' 창을 지울 때와 같은 방식이다. NewFileCommand 를 쓰던 --dialog-shots 는 AttachBlankForDiagnostics 로 바꿨다 (이름에 '진단 전용'을 박아 UI 에서 다시 부르지 못하게 했다). ## 없애자마자 드러난 것 문서가 아예 없는 상태가 <b>기본</b>이 되니 속성 패널에 정렬 바와 간격값이 그대로 남아 있었다. CurrentDesigner.Inspector 가 null 이면 안쪽 Visibility 바인딩이 전부 실패하고, WPF 는 <b>실패한 바인딩을 기본값(Visible)으로 떨군다</b> — Collapsed 가 아니다. 선택이 없다는 안내와 정렬 바가 동시에 떠 있었다. 열린 서식이 없으면 인스펙터를 접는다. 그리고 이 회귀는 값으로 잡히지 않으므로 시각 게이트에 대조군을 넣었다 — 00-main-default(문서 있음 → 인스펙터 보임) 대 00d-main-empty(문서 없음 → 접힘). 대조군 없이 빈 화면만 찍으면 "원래 그랬던 것"과 구분되지 않는다. ## 게이트 - dotnet test 323/323 - --edit-smoke 실패 0 - --dialog-shots FAIL 0 (00d-main-empty 추가) - --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9bff3dd5f6
commit
3ef1937902
@@ -130,6 +130,12 @@ public static class DialogShots
|
|||||||
// 'DB에서 열기' 대화상자를 지웠다. 그 자리를 좌측 서식 목록 샷이 대신한다 —
|
// 'DB에서 열기' 대화상자를 지웠다. 그 자리를 좌측 서식 목록 샷이 대신한다 —
|
||||||
// 안 그러면 서식명 잘림을 잡을 자리가 게이트에서 통째로 사라진다.
|
// 안 그러면 서식명 잘림을 잡을 자리가 게이트에서 통째로 사라진다.
|
||||||
("01-sheet-list", () => NewMainShell(1440, 920, leftTab: 0, sheets: SampleSheets())),
|
("01-sheet-list", () => NewMainShell(1440, 920, leftTab: 0, sheets: SampleSheets())),
|
||||||
|
// 문서 없는 시작 화면 — '새 서식'을 없앤 뒤로는 이것이 <b>기본 상태</b>다.
|
||||||
|
// 여기가 대조군이다: 00-main-default 는 문서가 있어 인스펙터가 보여야 하고,
|
||||||
|
// 이 샷은 없어서 접혀야 한다. 접히지 않으면 DataContext 가 null 인 채로
|
||||||
|
// 안쪽 Visibility 바인딩이 전부 실패해 정렬 바·간격값이 남는다(WPF 는 실패를 Visible 로 떨군다).
|
||||||
|
("00d-main-empty", () => NewMainShell(1440, 920, leftTab: 0,
|
||||||
|
sheets: SampleSheets(), withDocument: false)),
|
||||||
("02-sheet-history", () => new Views.SheetHistoryDialogView("S999", "표본 서식", SampleVersions())),
|
("02-sheet-history", () => new Views.SheetHistoryDialogView("S999", "표본 서식", SampleVersions())),
|
||||||
("03-query-editor", () => NewQueryEditor(designer,
|
("03-query-editor", () => NewQueryEditor(designer,
|
||||||
"SELECT ChtNum, PatNam FROM P_PatMst\nWHERE ChtNum = <<M.CMM.HISOperatingInfo.bzPatientInfo.ChtNum>>")),
|
"SELECT ChtNum, PatNam FROM P_PatMst\nWHERE ChtNum = <<M.CMM.HISOperatingInfo.bzPatientInfo.ChtNum>>")),
|
||||||
@@ -226,7 +232,7 @@ public static class DialogShots
|
|||||||
/// 빈 껍데기를 찍으면 잘림을 볼 수 없다.
|
/// 빈 껍데기를 찍으면 잘림을 볼 수 없다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static Window NewMainShell(double width, double height, int leftTab = 1,
|
private static Window NewMainShell(double width, double height, int leftTab = 1,
|
||||||
List<SheetSummary>? sheets = null)
|
List<SheetSummary>? sheets = null, bool withDocument = true)
|
||||||
{
|
{
|
||||||
var window = new Views.MainView
|
var window = new Views.MainView
|
||||||
{
|
{
|
||||||
@@ -240,7 +246,10 @@ public static class DialogShots
|
|||||||
{
|
{
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
shell.NewFileCommand?.Execute(null);
|
if (withDocument)
|
||||||
|
{
|
||||||
|
shell.AttachBlankForDiagnostics();
|
||||||
|
}
|
||||||
shell.SelectedLeftTabIndex = leftTab;
|
shell.SelectedLeftTabIndex = leftTab;
|
||||||
// 진단 모드는 Loaded 커맨드를 안 돌리므로 목록이 비어 있다 —
|
// 진단 모드는 Loaded 커맨드를 안 돌리므로 목록이 비어 있다 —
|
||||||
// 빈 목록을 찍으면 서식명 잘림을 볼 수 없다. 표본을 직접 넣는다.
|
// 빈 목록을 찍으면 서식명 잘림을 볼 수 없다. 표본을 직접 넣는다.
|
||||||
|
|||||||
@@ -647,11 +647,12 @@
|
|||||||
BorderBrush="{DynamicResource B.Line}" BorderThickness="0,0,0,1" Padding="8,5,8,0">
|
BorderBrush="{DynamicResource B.Line}" BorderThickness="0,0,0,1" Padding="8,5,8,0">
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
|
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
|
||||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom">
|
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom">
|
||||||
|
<!--
|
||||||
|
탭 흐름만 둔다. 전에는 옆에 '새 서식 탭(+)' 버튼이 있었으나
|
||||||
|
서식은 반드시 목록에서 골라 연다 — 코드 없는 빈 문서는
|
||||||
|
DB 에 저장할 수 없어서, 만들 수 있게 두면 그린 뒤에 막힌다.
|
||||||
|
-->
|
||||||
<StackPanel Orientation="Horizontal" IsItemsHost="True" />
|
<StackPanel Orientation="Horizontal" IsItemsHost="True" />
|
||||||
<!-- 새 서식 탭(+) — 탭 흐름 바로 옆([200] 문서탭 관행) -->
|
|
||||||
<Button Content="+" Command="{Binding NewFileCommand}" Style="{StaticResource Subtle}"
|
|
||||||
Width="26" Height="24" Padding="0" Margin="2,0,0,3" FontSize="13"
|
|
||||||
VerticalAlignment="Center" ToolTip="새 서식 탭"/>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
@@ -206,7 +206,6 @@ internal sealed class MainViewModel : ViewModelBase
|
|||||||
public MainViewModel()
|
public MainViewModel()
|
||||||
{
|
{
|
||||||
LoadedCommand = new Command(async (sender, e) => await OnLoadedAsync());
|
LoadedCommand = new Command(async (sender, e) => await OnLoadedAsync());
|
||||||
NewFileCommand = new Command((sender, e) => OnNewFile());
|
|
||||||
OpenFileCommand = new Command((sender, e) => OnOpenFile());
|
OpenFileCommand = new Command((sender, e) => OnOpenFile());
|
||||||
// Ctrl+S 가 이 커맨드에 걸려 있다. 문서 출처로 갈라야 한다 —
|
// Ctrl+S 가 이 커맨드에 걸려 있다. 문서 출처로 갈라야 한다 —
|
||||||
// DB 에서 연 서식에서 Ctrl+S 를 누르면 OS 저장 대화상자가 뜨고 디스크에 XML 이 쓰였다.
|
// DB 에서 연 서식에서 Ctrl+S 를 누르면 OS 저장 대화상자가 뜨고 디스크에 XML 이 쓰였다.
|
||||||
@@ -258,9 +257,6 @@ internal sealed class MainViewModel : ViewModelBase
|
|||||||
/// <summary>창 로드</summary>
|
/// <summary>창 로드</summary>
|
||||||
public ICustomCommand? LoadedCommand { get; set; }
|
public ICustomCommand? LoadedCommand { get; set; }
|
||||||
|
|
||||||
/// <summary>새 서식</summary>
|
|
||||||
public ICustomCommand? NewFileCommand { get; set; }
|
|
||||||
|
|
||||||
/// <summary>서식 XML 열기</summary>
|
/// <summary>서식 XML 열기</summary>
|
||||||
public ICustomCommand? OpenFileCommand { get; set; }
|
public ICustomCommand? OpenFileCommand { get; set; }
|
||||||
|
|
||||||
@@ -497,8 +493,7 @@ internal sealed class MainViewModel : ViewModelBase
|
|||||||
{
|
{
|
||||||
await LoadSheetListAsync();
|
await LoadSheetListAsync();
|
||||||
|
|
||||||
// 기동 인자로 서식을 지정했으면 빈 새 문서를 만들지 않는다 — 레거시도 해당 서식만 연다.
|
// 기동 인자로 서식을 지정했으면 그것만 연다 — 레거시도 그렇다.
|
||||||
// 열기에 실패하면(디자인 없음/권한 거부/코드 오타) 빈 문서로 폴백해 앱이 빈 껍데기가 되지 않게 한다.
|
|
||||||
if (PendingSheetCode is { Length: > 0 } shtCod)
|
if (PendingSheetCode is { Length: > 0 } shtCod)
|
||||||
{
|
{
|
||||||
PendingSheetCode = null;
|
PendingSheetCode = null;
|
||||||
@@ -509,22 +504,22 @@ internal sealed class MainViewModel : ViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OnNewFile();
|
// 아무것도 열지 않은 상태로 둔다. 전에는 빈 새 문서를 만들어 두었는데,
|
||||||
SelectedLeftTabIndex = 0; // 시작 화면은 서식 목록 탭(초기 빈 문서로 레이어 탭 전환되는 것 되돌림)
|
// 그건 <b>저장할 수 없는 문서</b>다 — 서식 코드가 없으니 DB 저장이 막히고,
|
||||||
|
// 사용자는 한참 그려 넣은 뒤에야 그 사실을 알게 된다.
|
||||||
|
// 서식은 반드시 목록에서 골라 연다(그래야 코드·권한·기존 디자인이 함께 온다).
|
||||||
|
SelectedLeftTabIndex = 0;
|
||||||
|
StatusText = "서식 목록에서 서식을 골라 여세요.";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnNewFile()
|
/// <summary>
|
||||||
{
|
/// 빈 문서를 붙인다 — <b>진단 전용</b>이다(--dialog-shots 가 화면을 찍으려면 문서가 필요하다).
|
||||||
try
|
///
|
||||||
{
|
/// UI 에는 '새 서식'이 없다. 코드 없는 문서는 DB 에 저장할 수 없고,
|
||||||
AttachDocument(new DesignerViewModel(dataBusiness.CreateNew()));
|
/// 그린 뒤에 그것을 알게 되는 것이 이 앱에서 가장 비싼 실수였다.
|
||||||
StatusText = "새 서식 (720×856)";
|
/// </summary>
|
||||||
}
|
internal void AttachBlankForDiagnostics()
|
||||||
catch (Exception ex)
|
=> AttachDocument(new DesignerViewModel(dataBusiness.CreateNew()));
|
||||||
{
|
|
||||||
DialogService.ShowError("새 서식 만들기", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnOpenFile()
|
private void OnOpenFile()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
처리하며, 여기 올리면 인스펙터·검색 상자 등 TextBox 의 표준 편집 키와 충돌한다.
|
처리하며, 여기 올리면 인스펙터·검색 상자 등 TextBox 의 표준 편집 키와 충돌한다.
|
||||||
-->
|
-->
|
||||||
<Window.InputBindings>
|
<Window.InputBindings>
|
||||||
<KeyBinding Key="N" Modifiers="Control" Command="{Binding NewFileCommand}"/>
|
|
||||||
<!-- Ctrl+O 는 코드비하인드에서 서식 목록으로 보낸다(파일 대화상자가 아니다) -->
|
<!-- Ctrl+O 는 코드비하인드에서 서식 목록으로 보낸다(파일 대화상자가 아니다) -->
|
||||||
<KeyBinding Key="S" Modifiers="Control" Command="{Binding SaveFileCommand}"/>
|
<KeyBinding Key="S" Modifiers="Control" Command="{Binding SaveFileCommand}"/>
|
||||||
<KeyBinding Key="P" Modifiers="Control" Command="{Binding PrintCommand}"/>
|
<KeyBinding Key="P" Modifiers="Control" Command="{Binding PrintCommand}"/>
|
||||||
@@ -164,7 +163,6 @@
|
|||||||
edit-smoke 직렬화 왕복)이 그 경로를 쓴다. UI 진입점만 없앤 것이다.
|
edit-smoke 직렬화 왕복)이 그 경로를 쓴다. UI 진입점만 없앤 것이다.
|
||||||
-->
|
-->
|
||||||
<MenuItem Header="파일(_F)">
|
<MenuItem Header="파일(_F)">
|
||||||
<MenuItem Header="새 서식(_N)" Command="{Binding NewFileCommand}" InputGestureText="Ctrl+N"/>
|
|
||||||
<MenuItem Header="서식 목록에서 열기(_O)" Click="OnOpenFromListClick" InputGestureText="Ctrl+O"/>
|
<MenuItem Header="서식 목록에서 열기(_O)" Click="OnOpenFromListClick" InputGestureText="Ctrl+O"/>
|
||||||
<Separator/>
|
<Separator/>
|
||||||
<MenuItem Header="저장(_S)" Command="{Binding SaveToDbCommand}" InputGestureText="Ctrl+S"
|
<MenuItem Header="저장(_S)" Command="{Binding SaveToDbCommand}" InputGestureText="Ctrl+S"
|
||||||
@@ -752,9 +750,8 @@
|
|||||||
HorizontalAlignment="Center" Margin="0,16,0,6"/>
|
HorizontalAlignment="Center" Margin="0,16,0,6"/>
|
||||||
<TextBlock Foreground="{DynamicResource B.Muted}" FontSize="12.5" TextAlignment="Center"
|
<TextBlock Foreground="{DynamicResource B.Muted}" FontSize="12.5" TextAlignment="Center"
|
||||||
TextWrapping="Wrap" HorizontalAlignment="Center" Margin="0,0,0,20"
|
TextWrapping="Wrap" HorizontalAlignment="Center" Margin="0,0,0,20"
|
||||||
Text="새 서식을 만들거나, 왼쪽 서식 목록에서 기존 서식을 두 번 눌러 엽니다."/>
|
Text="왼쪽 서식 목록에서 서식을 두 번 눌러 엽니다. (F4 또는 Ctrl+O)"/>
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||||
<Button Content="새 서식" Command="{Binding NewFileCommand}" Padding="16,7" Margin="0,0,8,0"/>
|
|
||||||
<Button Content="서식 목록에서 열기" Click="OnOpenFromListClick" Padding="16,7"
|
<Button Content="서식 목록에서 열기" Click="OnOpenFromListClick" Padding="16,7"
|
||||||
IsEnabled="{Binding CanUseDb}"/>
|
IsEnabled="{Binding CanUseDb}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
@@ -771,7 +768,17 @@
|
|||||||
BorderBrush="{DynamicResource B.Line}" BorderThickness="0,0,0,1">
|
BorderBrush="{DynamicResource B.Line}" BorderThickness="0,0,0,1">
|
||||||
<TextBlock Text="속성" FontWeight="Bold" Foreground="{DynamicResource B.Muted}"/>
|
<TextBlock Text="속성" FontWeight="Bold" Foreground="{DynamicResource B.Muted}"/>
|
||||||
</Border>
|
</Border>
|
||||||
<v:InspectorView x:Name="Inspector" DataContext="{Binding CurrentDesigner.Inspector}"/>
|
<!--
|
||||||
|
열린 서식이 없으면 인스펙터를 <b>접는다.</b>
|
||||||
|
DataContext 가 null 이면 안쪽 Visibility 바인딩이 전부 실패하고,
|
||||||
|
WPF 는 실패한 바인딩을 기본값(Visible)으로 떨어뜨린다 —
|
||||||
|
그래서 선택이 없는데도 정렬 바와 간격값이 남아 있었다.
|
||||||
|
'새 서식'을 없애면서 시작 화면에 문서가 아예 없어졌고, 그 자리가 드러났다.
|
||||||
|
-->
|
||||||
|
<v:InspectorView x:Name="Inspector" DataContext="{Binding CurrentDesigner.Inspector}"
|
||||||
|
Visibility="{Binding DataContext.HasOpenDocuments,
|
||||||
|
RelativeSource={RelativeSource AncestorType=Window},
|
||||||
|
Converter={StaticResource BoolToVisibility}}"/>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
Reference in New Issue
Block a user