using Microsoft.UI; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Markup; using Microsoft.UI.Xaml.Media; using Sonex.Client.Views; using System; using System.Globalization; using System.Reflection; namespace Sonex.Client.Controls; public delegate void TabViewItemSelectedEventHandler(object sender, TabViewItem item); [ContentProperty(Name = nameof(View))] public sealed class TabViewItem : SelectorBarItem { private const string SelectorBarItemPaddingResourceKey = "SelectorBarItemPadding"; public static readonly DependencyProperty ViewProperty = DependencyProperty.Register( nameof(View), typeof(IView), typeof(TabViewItem), new PropertyMetadata(null, OnViewChanged)); public static readonly DependencyProperty KeyPathProperty = DependencyProperty.Register( nameof(KeyPath), typeof(string), typeof(TabViewItem), new PropertyMetadata(string.Empty)); public static readonly DependencyProperty ItemTypeProperty = DependencyProperty.Register( nameof(ItemType), typeof(Type), typeof(TabViewItem), new PropertyMetadata(null)); public TabViewItem() { ApplyTabPadding(new Thickness(16, 8, 16, 6)); Background = new SolidColorBrush(Colors.Transparent); HorizontalAlignment = HorizontalAlignment.Stretch; HorizontalContentAlignment = HorizontalAlignment.Stretch; VerticalContentAlignment = VerticalAlignment.Stretch; } public string Header { get => Text; set => Text = value ?? string.Empty; } public Thickness TabPadding { get => Padding; set => ApplyTabPadding(value); } public IView? View { get => (IView?)GetValue(ViewProperty); set => SetValue(ViewProperty, value); } public string KeyPath { get => (string)GetValue(KeyPathProperty); set => SetValue(KeyPathProperty, value ?? string.Empty); } public Type? ItemType { get => (Type?)GetValue(ItemTypeProperty); set => SetValue(ItemTypeProperty, value); } public event TabViewItemSelectedEventHandler? OnSelect; internal event EventHandler? ViewChanged; internal void Load(object? item) { if (View == null) { return; } if (item == null) { View.Clear(); return; } var itemType = ItemType; if (itemType != null && !itemType.IsInstanceOfType(item)) { View.Clear(); return; } var key = ResolveKey(item); if (string.IsNullOrWhiteSpace(key)) { View.Clear(); return; } View.Load(key); } internal void RaiseOnSelect() { OnSelect?.Invoke(this, this); } private static void OnViewChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs _) { if (dependencyObject is TabViewItem item) { item.ViewChanged?.Invoke(item, EventArgs.Empty); } } private string ResolveKey(object item) { if (string.IsNullOrWhiteSpace(KeyPath)) { return Convert.ToString(item, CultureInfo.CurrentCulture) ?? string.Empty; } object? value = item; foreach (var part in KeyPath.Split('.', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) { if (value == null) { return string.Empty; } var property = value.GetType().GetProperty(part, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase); if (property == null) { return string.Empty; } value = property.GetValue(value); } return Convert.ToString(value, CultureInfo.CurrentCulture) ?? string.Empty; } private void ApplyTabPadding(Thickness padding) { Padding = padding; Resources[SelectorBarItemPaddingResourceKey] = padding; } }