using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media; using System; namespace Lattice.Layout.UI.WinUI.Controls; /// /// Контрол для отображения содержимого конечного элемента раскладки. /// Является контейнером для реального UI-контента, подставляемого через ContentResolver. /// public sealed class WinUIItemControl : ContentControl { /// /// Идентификатор содержимого, связанного с данным элементом. /// Используется для подстановки реального UI-контрола через ContentResolver. /// public string? ContentId { get => (string?)GetValue(ContentIdProperty); set => SetValue(ContentIdProperty, value); } public static readonly DependencyProperty ContentIdProperty = DependencyProperty.Register( nameof(ContentId), typeof(string), typeof(WinUIItemControl), new PropertyMetadata(default(string), OnContentIdChanged)); /// /// Делегат, который должен вернуть реальный UI-контент по ContentId. /// Устанавливается WinUILayoutHost. /// public Func? ContentResolver { get => (Func?)GetValue(ContentResolverProperty); set => SetValue(ContentResolverProperty, value); } public static readonly DependencyProperty ContentResolverProperty = DependencyProperty.Register( nameof(ContentResolver), typeof(Func), typeof(WinUIItemControl), new PropertyMetadata(null, OnContentResolverChanged)); /// /// Вызывается, когда контент успешно загружен. /// public event Action? ContentLoaded; /// /// Вызывается, когда контент был очищен (Detach). /// public event Action? ContentCleared; /// /// Создаёт новый экземпляр . /// public WinUIItemControl() { HorizontalContentAlignment = HorizontalAlignment.Stretch; VerticalContentAlignment = VerticalAlignment.Stretch; // Fallback-контент, если ContentResolver не установлен Content = CreatePlaceholder(); } private static void OnContentIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is WinUIItemControl control) control.TryLoadContent(); } private static void OnContentResolverChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is WinUIItemControl control) control.TryLoadContent(); } /// /// Пытается загрузить реальный контент по ContentId. /// private void TryLoadContent() { if (ContentId is null || ContentResolver is null) { Content = CreatePlaceholder(); return; } var resolved = ContentResolver(ContentId); if (resolved is null) { Content = CreatePlaceholder($"Контент '{ContentId}' не найден"); return; } Content = resolved; ContentLoaded?.Invoke(this); } /// /// Очищает контент (используется визуалом при Detach). /// public void ClearContent() { Content = CreatePlaceholder(); ContentCleared?.Invoke(this); } /// /// Создаёт placeholder-контент, отображаемый до загрузки реального UI. /// private static UIElement CreatePlaceholder(string? message = null) { return new Border { Background = new SolidColorBrush(Microsoft.UI.Colors.Transparent), BorderBrush = new SolidColorBrush(Microsoft.UI.Colors.Gray), BorderThickness = new Thickness(1), Padding = new Thickness(8), Child = new TextBlock { Text = message ?? "Нет содержимого", Opacity = 0.6, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center } }; } }