20using System.Collections.Generic;
21using System.Collections.ObjectModel;
22using System.ComponentModel;
25using System.Windows.Controls;
26using System.Windows.Markup;
27using System.Windows.Threading;
28using Dreamine.MVVM.Core;
29using Dreamine.MVVM.Interfaces;
60 [ContentProperty(nameof(Items))]
75 public ObservableCollection<DreamineTabHostItem>
Items {
get; } =
new ObservableCollection<DreamineTabHostItem>();
95 private readonly Dictionary<string, FrameworkElement>
_views =
new Dictionary<string, FrameworkElement>();
105 private readonly List<string>
_order =
new List<string>();
165 private readonly Dictionary<FrameworkElement, bool>
_lastVisibilityState =
new Dictionary<FrameworkElement, bool>();
167 #region ===== Popup awareness: Flag DP & Readonly DP =====
178 DependencyProperty.Register(
182 new PropertyMetadata(
false));
207 DependencyProperty.RegisterReadOnly(
211 new PropertyMetadata(
false));
270 DependencyProperty.Register(
272 typeof(ObservableCollection<string>),
302 DependencyProperty.Register(
304 typeof(ObservableCollection<string>),
331 DependencyProperty.Register(
360 DependencyProperty.Register(
389 DependencyProperty.Register(
420 DependencyProperty.Register(
449 DependencyProperty.Register(
478 DependencyProperty.Register(
594 ctrl.Dispatcher.BeginInvoke(
new Action(() =>
596 ctrl.SwitchToViewInternal(viewName);
597 }), DispatcherPriority.Background);
655 base.OnInitialized(e);
658 Dispatcher.InvokeAsync(() =>
661 }, DispatcherPriority.ContextIdle);
685 Dispatcher.BeginInvoke(
new Action(() =>
702 }), DispatcherPriority.Input);
728 if (
string.IsNullOrWhiteSpace(targetKey))
745 if (!isPopup &&
_views.TryGetValue(targetKey, out var nextView))
770 if (
string.IsNullOrWhiteSpace(targetKey))
773 if (!
string.IsNullOrWhiteSpace(raw) &&
774 raw.EndsWith(
"_Popup", StringComparison.OrdinalIgnoreCase))
776 string withoutSuffix = raw[..^6];
781 if (
string.IsNullOrWhiteSpace(targetKey))
805 if (newIndex < 0) newIndex = 0;
806 if (newIndex >=
_order.Count) newIndex = _order.Count - 1;
813 var newKey =
_order.ElementAtOrDefault(newIndex);
814 if (
string.IsNullOrWhiteSpace(newKey))
819 var newView =
_views[newKey];
865 if (sender is not FrameworkElement fe)
870 if (fe.DataContext is not IVisibilityAware vm)
875 bool isVisible = (bool)e.NewValue;
923 if (pairs.Count == 0)
936 foreach (var (name, typeName) in pairs)
942 string actualTypeName = typeName.EndsWith(
"_Popup", StringComparison.OrdinalIgnoreCase)
950 if (result.View is
null)
955 _views[name] = result.View;
965 result.View.Visibility =
UseSingletonView ? Visibility.Collapsed : Visibility.Visible;
1001 if (fromItems.Count > 0)
1029 var result =
new List<(string name, string typeName)>();
1036 foreach (var it
in Items)
1038 var raw = it?.Content?.ToString() ??
string.Empty;
1039 if (
string.IsNullOrWhiteSpace(raw))
1045 string typeName = it!.Popup && !raw.EndsWith(
"_Popup", StringComparison.OrdinalIgnoreCase)
1049 string name = !
string.IsNullOrWhiteSpace(it.Key)
1051 :
DeriveSimpleKeyFromType(typeName.EndsWith(
"_Popup", StringComparison.OrdinalIgnoreCase) ? typeName[..^6] : typeName);
1054 if (!
string.IsNullOrWhiteSpace(it.Type))
1057 if (it.Popup && !typeName.EndsWith(
"_Popup", StringComparison.OrdinalIgnoreCase))
1059 typeName +=
"_Popup";
1063 result.Add((name, typeName));
1097 var it =
Items.ElementAtOrDefault(index);
1098 return it?.Content?.ToString();
1122 foreach (var (name, typeName) in pairs)
1126 UserControl? view =
null;
1127 foreach (var cand
in candidates)
1130 if (view !=
null)
break;
1176 => DesignerProperties.GetIsInDesignMode(
this);
1210 private static List<(
string name,
string typeName)>
EnsureUniqueNames(List<(
string name,
string typeName)> pairs)
1212 var result =
new List<(string name, string typeName)>(pairs);
1213 var seen =
new HashSet<string>(StringComparer.Ordinal);
1215 for (
int i = 0; i < result.Count; i++)
1217 var (n, t) = result[i];
1218 if (
string.IsNullOrWhiteSpace(n))
1235 while (!seen.Add(c));
1276 ObservableCollection<string>? names,
1277 ObservableCollection<string>? types)
1279 var result =
new List<(string name, string typeName)>();
1281 var hasNames = names is { Count: > 0 };
1282 var hasTypes = types is { Count: > 0 };
1284 if (!hasNames && !hasTypes)
1289 if (hasNames && hasTypes)
1291 var count = Math.Min(names!.Count, types!.Count);
1292 for (
int i = 0; i < count; i++)
1294 var typeName = types[i] ??
string.Empty;
1295 var name =
string.IsNullOrWhiteSpace(names[i])
1299 result.Add((name, typeName));
1304 foreach (var t
in types!)
1306 var typeName = t ??
string.Empty;
1308 result.Add((name, typeName));
1313 foreach (var n
in names!)
1315 var typeName = n ??
string.Empty;
1317 result.Add((name, typeName));
1349 =>
string.IsNullOrWhiteSpace(raw)
1351 : (raw.Contains(
'.') ? raw.Split(
'.').Last() : raw);
1395 var list =
new List<string> { raw };
1397 if (!
string.IsNullOrWhiteSpace(asmHint) && !raw.Contains(
","))
1399 list.Add($
"{raw}, {asmHint}");
1402 if (!raw.Contains(
'.') && !
string.IsNullOrWhiteSpace(baseNs))
1404 var full = $
"{baseNs}.{raw}";
1407 if (!
string.IsNullOrWhiteSpace(asmHint))
1409 list.Add($
"{full}, {asmHint}");
1413 return list.Distinct().ToArray();
1446 if (typeName.Contains(
","))
1448 t = Type.GetType(typeName, throwOnError:
false, ignoreCase:
false);
1456 if (t ==
null || !typeof(UserControl).IsAssignableFrom(t))
1463 return Activator.CreateInstance(t) as UserControl;
1467 return Activator.CreateInstance(t, nonPublic:
true) as UserControl;
1510 var asms = AppDomain.CurrentDomain.GetAssemblies();
1512 if (name.Contains(
'.'))
1514 foreach (var
asm in asms)
1516 var t =
asm.GetType(name, throwOnError:
false, ignoreCase:
false);
1524 foreach (var
asm in asms)
1528 var t =
asm.GetTypes().FirstOrDefault(x => x.Name == name);
1569 return new UserControl
1571 Content =
new Border
1573 Background = System.Windows.Media.Brushes.White,
1574 BorderBrush = System.Windows.Media.Brushes.LightSteelBlue,
1575 BorderThickness =
new Thickness(2),
1576 CornerRadius =
new CornerRadius(6),
1577 Padding =
new Thickness(8),
1578 Child =
new TextBlock
1580 Text = $
"[design] {title}",
1582 Foreground = System.Windows.Media.Brushes.Black
1614 if (view.DataContext !=
null)
1627 var vm = DMContainer.Resolve(vmType);
1630 view.DataContext = vm;
1673 var fullCandidate = viewType.FullName +
"ViewModel";
1674 var nsCandidate = $
"{viewType.Namespace}.{viewType.Name}ViewModel";
1675 var shortCandidate = viewType.Name +
"ViewModel";
1678 if (t !=
null)
return t;
1681 if (t !=
null)
return t;
1713 DependencyProperty.Register(
1717 new PropertyMetadata(
false));
1742 DependencyProperty.Register(
1746 new PropertyMetadata(
string.Empty));
1771 DependencyProperty.Register(
1775 new PropertyMetadata(
string.Empty));
static void OnContentInputsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
override void OnInitialized(EventArgs e)
List<(string name, string typeName)> BuildPairsFromItemsOrDps()
static readonly DependencyProperty DesignBaseNamespaceHintProperty
static readonly DependencyProperty SelectViewProperty
void InitDesignViews(List<(string name, string typeName)> pairs)
static string[] BuildDesignTypeCandidates(string raw, string baseNs, string asmHint)
string? GetDeclaredRawEntryAt(int index)
static readonly DependencyProperty UseSingletonViewProperty
static List<(string name, string typeName)> EnsureUniqueNames(List<(string name, string typeName)> pairs)
static readonly DependencyPropertyKey IsCurrentTargetPopupPropertyKey
static ? UserControl TryCreateDesignView(string typeName)
static readonly DependencyProperty CurrentViewProperty
static string DeriveSimpleKeyFromType(string raw)
static readonly DependencyProperty AutoWireDesignViewModelProperty
readonly List< string > _order
static ? Type ResolveDesignViewModelType(Type viewType)
readonly Dictionary< FrameworkElement, bool > _lastVisibilityState
static UserControl MakeDesignPlaceholder(string title)
static readonly DependencyProperty IsCurrentTargetPopupProperty
static readonly DependencyProperty TargetAnalyzedProperty
ViewSwitcher? _viewSwitcher
List<(string name, string typeName)> BuildPairsFromItems()
static void OnSelectViewChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
ObservableCollection< DreamineTabHostItem > Items
static List<(string name, string typeName)> BuildNameTypePairs_NoMutation(ObservableCollection< string >? names, ObservableCollection< string >? types)
static void OnCurrentViewChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
static void OnDesignHintChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
bool AutoWireDesignViewModel
string DesignAssemblyHint
FrameworkElement? _currentView
ObservableCollection< string > ContentList
static readonly DependencyProperty ContentListProperty
readonly Dictionary< string, FrameworkElement > _views
void OnRootIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
void UpdateVisibleViewDesign()
void SwitchToViewInternal(string? targetKey)
static readonly DependencyProperty DesignAssemblyHintProperty
static ? Type FindTypeByName(string name)
readonly PopupWindowManager _popupManager
static void AttachDesignViewModelIfEmpty(UserControl view)
string DesignBaseNamespaceHint
ObservableCollection< string > ContentTypeList
bool IsCurrentTargetPopup
static readonly DependencyProperty ContentTypeListProperty
static readonly DependencyProperty PopupProperty
static readonly DependencyProperty KeyProperty
static readonly DependencyProperty TypeProperty
static PopupWindowManager Instance
static LoadedViewInfo LoadViewWithViewModel(string typeName, bool useSingletonView)