135 lines
4.7 KiB
C#
135 lines
4.7 KiB
C#
using Microsoft.UI.Xaml;
|
||
using Microsoft.UI.Xaml.Controls;
|
||
using Microsoft.UI.Xaml.Media;
|
||
using System;
|
||
|
||
namespace Lattice.Layout.UI.WinUI.Controls;
|
||
|
||
/// <summary>
|
||
/// Контрол для отображения содержимого конечного элемента раскладки.
|
||
/// Является контейнером для реального UI-контента, подставляемого через ContentResolver.
|
||
/// </summary>
|
||
public sealed class WinUIItemControl : ContentControl
|
||
{
|
||
/// <summary>
|
||
/// Идентификатор содержимого, связанного с данным элементом.
|
||
/// Используется для подстановки реального UI-контрола через ContentResolver.
|
||
/// </summary>
|
||
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));
|
||
|
||
/// <summary>
|
||
/// Делегат, который должен вернуть реальный UI-контент по ContentId.
|
||
/// Устанавливается WinUILayoutHost.
|
||
/// </summary>
|
||
public Func<string, UIElement?>? ContentResolver
|
||
{
|
||
get => (Func<string, UIElement?>?)GetValue(ContentResolverProperty);
|
||
set => SetValue(ContentResolverProperty, value);
|
||
}
|
||
|
||
public static readonly DependencyProperty ContentResolverProperty =
|
||
DependencyProperty.Register(
|
||
nameof(ContentResolver),
|
||
typeof(Func<string, UIElement?>),
|
||
typeof(WinUIItemControl),
|
||
new PropertyMetadata(null, OnContentResolverChanged));
|
||
|
||
/// <summary>
|
||
/// Вызывается, когда контент успешно загружен.
|
||
/// </summary>
|
||
public event Action<WinUIItemControl>? ContentLoaded;
|
||
|
||
/// <summary>
|
||
/// Вызывается, когда контент был очищен (Detach).
|
||
/// </summary>
|
||
public event Action<WinUIItemControl>? ContentCleared;
|
||
|
||
/// <summary>
|
||
/// Создаёт новый экземпляр <see cref="WinUIItemControl"/>.
|
||
/// </summary>
|
||
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();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Пытается загрузить реальный контент по ContentId.
|
||
/// </summary>
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Очищает контент (используется визуалом при Detach).
|
||
/// </summary>
|
||
public void ClearContent()
|
||
{
|
||
Content = CreatePlaceholder();
|
||
ContentCleared?.Invoke(this);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создаёт placeholder-контент, отображаемый до загрузки реального UI.
|
||
/// </summary>
|
||
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
|
||
}
|
||
};
|
||
}
|
||
}
|