Dreamine.UI.Wpf.Controls 1.0.1
Dreamine.UI.Wpf.Controls 사용자 인터페이스 기능과 구성 요소를 제공합니다.
로딩중...
검색중...
일치하는것 없음
PopupWindowManager.cs
이 파일의 문서화 페이지로 가기
1using System.Diagnostics;
2using System.Windows;
3using System.Windows.Controls;
4using System.Windows.Media;
5using System.Windows.Media.Media3D;
7
9{
18 public class PopupWindowManager
19 {
28 public double Width { get; set; } = 800;
29
38 public double Height { get; set; } = 600;
39
48 public static PopupWindowManager Instance { get; } = new();
57 private readonly Dictionary<string, Window> _popupWindows = new();
58
107 public void SetPopupSize(string name, double width, double height)
108 {
109 _popupWindows[name].Width = width;
110 _popupWindows[name].Height = height;
111 }
112
121 public IReadOnlyDictionary<string, Window> Windows => _popupWindows;
122
195 public void CreatePopup(string name, LoadedViewInfo loadedViewInfo, double? popupWidth = null, double? popupHeight = null, bool centerOnScreen = false)
196 {
197 FrameworkElement view = loadedViewInfo.View
198 ?? loadedViewInfo.FrameworkView
199 ?? throw new InvalidOperationException($"Popup view '{name}' could not be created.");
200
201 object? viewModel = view.DataContext;
202
203 if (!Application.Current.Dispatcher.CheckAccess())
204 {
205 Application.Current.Dispatcher.Invoke(() => CreatePopup(name, loadedViewInfo, popupWidth, popupHeight, centerOnScreen));
206 return;
207 }
208
209 var owner = Application.Current?.MainWindow;
210
211 Window popup;
212
213 view.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
214 var desired = view.DesiredSize;
215
216 if (loadedViewInfo.View == null)
217 {
218 popup = new Window
219 {
220 Title = "",
221 Content = view,
222 DataContext = viewModel,
223 WindowStartupLocation = WindowStartupLocation.CenterScreen,
224 WindowStyle = WindowStyle.None,
225 ResizeMode = ResizeMode.NoResize,
226 Background = Brushes.White,
227 Width = desired.Width,
228 Height = desired.Height,
229 ShowInTaskbar = false,
230 Topmost = true,
231 };
232 }
233 else
234 {
235 popup = new Window
236 {
237 Title = "",
238 Content = view,
239 DataContext = viewModel,
240 WindowStartupLocation = WindowStartupLocation.CenterOwner,
241 WindowStyle = WindowStyle.None,
242 ResizeMode = ResizeMode.NoResize,
243 // AllowsTransparency=true는 Background가 완전 불투명(White)이라 시각적으로
244 // 필요 없고, 레이어드 윈도우(WS_EX_LAYERED)로 만들어져 일부 환경(원격 데스크톱/
245 // 가상 머신/특정 GPU 드라이버)에서 마우스 입력이 전달되지 않는 문제를 유발할 수
246 // 있어 제거했다.
247 ShowActivated = true,
248 Background = Brushes.White,
249 Width = desired.Width,
250 Height = desired.Height,
251 ShowInTaskbar = false,
252 Topmost = true
253 };
254 }
255
256 // 크기 조정
257 popup.Width = popupWidth ?? Width;
258 popup.Height = popupHeight ?? Height;
259
260 // centerOnScreen 플래그를 Tag에 저장해 이후 핸들러에서 참조
261 popup.Tag = centerOnScreen;
262
263 // 최초 Owner + 위치 설정 (여기서만 Owner를 건드림)
264 if (owner != null && owner.IsLoaded && owner.IsVisible)
265 {
266 try
267 {
268 popup.Owner = owner;
269 }
270 catch (Exception ex)
271 {
272 Debug.WriteLine($"[Popup] Owner 설정 실패({name}): {ex.Message}");
273 }
274
275 SetPopupPosition(popup, owner);
276 }
277 else
278 {
279 popup.WindowStartupLocation = WindowStartupLocation.CenterScreen;
280 }
281
282 // Owner가 나중에 보이게 되는 경우를 위한 보정
283 if (owner != null && !owner.IsVisible)
284 {
285#pragma warning disable CS1587 // Doxygen documents local functions; the C# compiler does not attach XML docs to them.
312 void OnOwnerReady(object? s, EventArgs e)
313 {
314 owner!.ContentRendered -= OnOwnerReady;
315
316 if (!popup.IsVisible)
317 return;
318
319 if (!owner.IsLoaded)
320 return;
321
322 try
323 {
324 popup.Owner = owner;
325 }
326 catch (Exception ex)
327 {
328 Debug.WriteLine($"[Popup] ContentRendered Owner 설정 실패({name}): {ex.Message}");
329 }
330
331 SetPopupPosition(popup, owner);
332 }
333#pragma warning restore CS1587
334
335 owner.ContentRendered += OnOwnerReady;
336 popup.Closed += (_, _) => owner!.ContentRendered -= OnOwnerReady;
337 }
338
339 popup.Loaded += (s, e) => popup.Hide();
340 popup.Show();
342
343 // 위치만 조정 (Owner는 다시 세팅하지 않음)
344 popup.IsVisibleChanged += (_, __) =>
345 {
346 if (!popup.IsVisible)
347 return;
348
349 SetPopupPosition(popup, owner);
350 };
351
352 // 앱 종료 중이면 그냥 닫고, 평소엔 Hide 재사용
353 popup.Closing += (s, e) =>
354 {
356
357 // Owner가 이미 죽었거나, 애플리케이션이 종료 진행 중이면 그냥 닫게 둠
358 var app = Application.Current;
359 bool ownerDead = owner == null || !owner.IsLoaded;
360 bool appShuttingDown = app is { ShutdownMode: ShutdownMode.OnExplicitShutdown } && app.MainWindow == null;
361
362 if (ownerDead || appShuttingDown)
363 {
364 // e.Cancel = false → 실제로 닫힘
365 return;
366 }
367
368 // 정상 동작 중에는 닫지 않고 숨김
369 SetPopupPosition(popup, owner);
370 popup.Hide();
371 e.Cancel = true;
372 };
373
374 _popupWindows[name] = popup;
375 }
376
401 private static void SetPopupPosition(Window popup, Window? owner)
402 {
403 bool centerOnScreen = popup.Tag is true;
404
405 if (centerOnScreen)
406 {
407 var screenWidth = SystemParameters.PrimaryScreenWidth;
408 var screenHeight = SystemParameters.PrimaryScreenHeight;
409 popup.Left = (screenWidth - popup.Width) / 2;
410 popup.Top = (screenHeight - popup.Height) / 2;
411 }
412 else if (owner != null && owner.IsLoaded && owner.IsVisible)
413 {
414 popup.Left = owner.Left + (owner.Width - popup.Width) / 2;
415 popup.Top = owner.Top + (owner.Height - popup.Height) / 2;
416 }
417 }
418
427 public void Clear()
428 {
429 foreach (var popup in _popupWindows.Values)
430 {
431 if (popup.IsVisible)
432 popup.Close();
433 }
434
435 _popupWindows.Clear();
436 }
437
470 public void Show(string name)
471 {
472 if (_popupWindows.TryGetValue(name, out var popup))
473 {
474 if (!popup.IsVisible)
475 popup.Show();
476
477 popup.Activate();
478 }
479 }
480
497 public void HideAllExcept(string name)
498 {
499 foreach (var kv in _popupWindows)
500 {
501 if (kv.Key != name && kv.Value.IsVisible)
502 kv.Value.Hide();
503 }
504 }
505
514 public void CloseAll()
515 {
516 foreach (var popup in _popupWindows.Values)
517 popup.Close();
518
519 _popupWindows.Clear();
520 }
521 }
522}
void SetPopupSize(string name, double width, double height)
static void SetPopupPosition(Window popup, Window? owner)
void CreatePopup(string name, LoadedViewInfo loadedViewInfo, double? popupWidth=null, double? popupHeight=null, bool centerOnScreen=false)
readonly Dictionary< string, Window > _popupWindows