Dreamine.UI.Wpf.Controls 1.0.1
Dreamine.UI.Wpf.Controls 사용자 인터페이스 기능과 구성 요소를 제공합니다.
로딩중...
검색중...
일치하는것 없음
DreamineTabControl.cs
이 파일의 문서화 페이지로 가기
1using System.Windows;
2using System.Windows.Controls;
3using System.Windows.Input;
4using System.Windows.Media;
5using Dreamine.MVVM.Core;
6using Dreamine.MVVM.ViewModels;
7
9{
18 public class DreamineTabControl : TabControl
19 {
29 {
30 DefaultStyleKeyProperty.OverrideMetadata(typeof(DreamineTabControl),
31 new FrameworkPropertyMetadata(typeof(DreamineTabControl)));
32
33 var uri = new Uri("/Dreamine.UI.Wpf.Themes;component/DreamineTabControlStyle.xaml", UriKind.RelativeOrAbsolute);
34
35 if (Application.Current != null)
36 {
37 bool alreadyAdded = Application.Current.Resources.MergedDictionaries
38 .OfType<ResourceDictionary>()
39 .Any(x => x.Source != null && x.Source.Equals(uri));
40
41 if (!alreadyAdded)
42 {
43 var dict = new ResourceDictionary { Source = uri };
44 Application.Current.Resources.MergedDictionaries.Add(dict);
45 }
46 }
47 }
48
58 {
59 this.PreviewMouseDoubleClick += OnTabItemDoubleClick;
60
61 CloseTabCommand = new RelayCommand<TabItem>(tab =>
62 {
63 if (tab != null && Items.Contains(tab))
64 {
65 Items.Remove(tab);
66 }
67 });
68
69 Loaded += (s, e) =>
70 {
71 foreach (var tab in Items.OfType<VsTabItem>())
72 {
74 }
75
76 ItemContainerGenerator.ItemsChanged += (s2, e2) =>
77 {
78 foreach (var item in Items.OfType<VsTabItem>())
79 {
80 if (item.ContextMenu == null)
82 }
83 };
84 };
85 }
86
111 private void OnTabItemDoubleClick(object sender, MouseButtonEventArgs e)
112 {
113 if (e.OriginalSource is DependencyObject originalSource)
114 {
115 var tab = FindParent<VsTabItem>(originalSource);
116 if (tab != null && tab.IsSelected)
117 {
118 DetachTab(tab);
119 e.Handled = true;
120 }
121 }
122 }
123
140 private void AttachContextMenu(VsTabItem tab)
141 {
142 var menu = new ContextMenu();
143
144 var detach = new MenuItem { Header = "Detach Tab" };
145 detach.Click += (s, e) => DetachTab(tab);
146
147 var close = new MenuItem { Header = "CloseAsync Tab" };
148 close.Click += (s, e) => RemoveTab(tab);
149
150 menu.Items.Add(detach);
151 menu.Items.Add(close);
152
153 tab.ContextMenu = menu;
154 }
155
180 private void OnCloseTabClick(object sender, RoutedEventArgs e)
181 {
182 if (TryGetTabItemFromContextMenu(sender, out var tab))
183 {
184 RemoveTab(tab);
185
186 if (tab.Content is IDisposable disposable)
187 {
188 disposable.Dispose();
189 }
190
191 tab.Content = null;
192 }
193 }
194
211 public void RemoveTab(TabItem tab)
212 {
213 if (tab == null) return;
214
215 if (Items.Contains(tab))
216 {
217 Items.Remove(tab);
218 }
219 }
220
245 private void OnDetachTabClick(object sender, RoutedEventArgs e)
246 {
247 if (TryGetTabItemFromContextMenu(sender, out var tab))
248 {
249 DetachTab(tab);
250 }
251 }
252
285 private bool TryGetTabItemFromContextMenu(object sender, out VsTabItem tab)
286 {
287 tab = null!;
288
289 if (sender is MenuItem menuItem &&
290 menuItem.Parent is ContextMenu ctx &&
291 ctx.PlacementTarget is DependencyObject target)
292 {
293 tab = FindParent<VsTabItem>(target);
294 return tab != null;
295 }
296
297 return false;
298 }
299
340 private T FindParent<T>(DependencyObject child) where T : DependencyObject
341 {
342 while (child != null)
343 {
344 if (child is T parent)
345 return parent;
346
347 child = VisualTreeHelper.GetParent(child);
348 }
349 return null!;
350 }
351
376 private void DetachTab(VsTabItem tab)
377 {
378 if (tab?.Content is not UIElement content)
379 return;
380
381 var header = tab.Header;
382 var icon = tab.Icon;
383 var isClosable = tab.IsClosable;
384
385 var floatWindow = new Window
386 {
387 Title = header?.ToString(),
388 Content = content,
389 Width = 800,
390 Height = 600,
391 Icon = icon,
392 };
393
394 floatWindow.Closed += (s, e) =>
395 {
396 // Restore tab when floating window is closed
397 AddTab(header?.ToString()!, content, icon, isClosable);
398 };
399
400 Items.Remove(tab);
401 floatWindow.Show();
402 }
403
452 public void AddTab(string title, UIElement content, ImageSource? icon = null, bool isClosable = true)
453 {
454 var newTab = new VsTabItem
455 {
456 Header = title,
457 Content = content,
458 Icon = icon!,
459 IsClosable = isClosable,
460 };
461
462 Items.Add(newTab);
463 SelectedItem = newTab;
464 }
465
474 public static readonly DependencyProperty CloseTabCommandProperty =
475 DependencyProperty.Register(nameof(CloseTabCommand), typeof(ICommand), typeof(DreamineTabControl), new PropertyMetadata(null));
476
485 public ICommand CloseTabCommand
486 {
487 get => (ICommand)GetValue(CloseTabCommandProperty);
488 set => SetValue(CloseTabCommandProperty, value);
489 }
490 }
491
500 public class VsTabItem : TabItem
501 {
510 public static readonly DependencyProperty IsClosableProperty =
511 DependencyProperty.Register(nameof(IsClosable), typeof(bool), typeof(VsTabItem), new PropertyMetadata(true));
512
521 public bool IsClosable
522 {
523 get => (bool)GetValue(IsClosableProperty);
524 set => SetValue(IsClosableProperty, value);
525 }
526
535 public static readonly DependencyProperty IconProperty =
536 DependencyProperty.Register(nameof(Icon), typeof(ImageSource), typeof(VsTabItem), new PropertyMetadata(null));
537
546 public ImageSource Icon
547 {
548 get => (ImageSource)GetValue(IconProperty);
549 set => SetValue(IconProperty, value);
550 }
551
552 #region Design Properties
553
562 public static readonly DependencyProperty TabHeaderBackgroundProperty =
563 DependencyProperty.Register(nameof(TabHeaderBackground), typeof(Brush), typeof(VsTabItem), new PropertyMetadata(Brushes.LightGray));
564
574 {
575 get => (Brush)GetValue(TabHeaderBackgroundProperty);
576 set => SetValue(TabHeaderBackgroundProperty, value);
577 }
578
587 public static readonly DependencyProperty TabHeaderSelectedBackgroundProperty =
588 DependencyProperty.Register(nameof(TabHeaderSelectedBackground), typeof(Brush), typeof(VsTabItem), new PropertyMetadata(Brushes.White));
589
599 {
600 get => (Brush)GetValue(TabHeaderSelectedBackgroundProperty);
601 set => SetValue(TabHeaderSelectedBackgroundProperty, value);
602 }
603
612 public static readonly DependencyProperty TabCornerRadiusProperty =
613 DependencyProperty.Register(nameof(TabCornerRadius), typeof(CornerRadius), typeof(VsTabItem), new PropertyMetadata(new CornerRadius(4)));
614
623 public CornerRadius TabCornerRadius
624 {
625 get => (CornerRadius)GetValue(TabCornerRadiusProperty);
626 set => SetValue(TabCornerRadiusProperty, value);
627 }
628
637 public static readonly DependencyProperty TabBorderThicknessProperty =
638 DependencyProperty.Register(nameof(TabBorderThickness), typeof(Thickness), typeof(VsTabItem), new PropertyMetadata(new Thickness(1)));
639
648 public Thickness TabBorderThickness
649 {
650 get => (Thickness)GetValue(TabBorderThicknessProperty);
651 set => SetValue(TabBorderThicknessProperty, value);
652 }
653
662 public static readonly DependencyProperty TabHeaderFontSizeProperty =
663 DependencyProperty.Register(nameof(TabHeaderFontSize), typeof(double), typeof(VsTabItem), new PropertyMetadata(12.0));
664
673 public double TabHeaderFontSize
674 {
675 get => (double)GetValue(TabHeaderFontSizeProperty);
676 set => SetValue(TabHeaderFontSizeProperty, value);
677 }
678
679 #endregion
680
689 static VsTabItem()
690 {
691 DefaultStyleKeyProperty.OverrideMetadata(typeof(VsTabItem),
692 new FrameworkPropertyMetadata(typeof(VsTabItem)));
693 }
694 }
695}
void OnCloseTabClick(object sender, RoutedEventArgs e)
void OnDetachTabClick(object sender, RoutedEventArgs e)
bool TryGetTabItemFromContextMenu(object sender, out VsTabItem tab)
void OnTabItemDoubleClick(object sender, MouseButtonEventArgs e)
void AddTab(string title, UIElement content, ImageSource? icon=null, bool isClosable=true)
static readonly DependencyProperty CloseTabCommandProperty
static readonly DependencyProperty TabBorderThicknessProperty
static readonly DependencyProperty TabHeaderBackgroundProperty
static readonly DependencyProperty TabHeaderFontSizeProperty
static readonly DependencyProperty IconProperty
static readonly DependencyProperty TabHeaderSelectedBackgroundProperty
static readonly DependencyProperty IsClosableProperty
static readonly DependencyProperty TabCornerRadiusProperty